am 8673ee75: am 9a35ef1b: Guarantee deflaters get cleaned up, even if subclassed.
Merge commit '8673ee75052e7398aa6f5925e968d6a0b2419be8'
* commit '8673ee75052e7398aa6f5925e968d6a0b2419be8':
Guarantee deflaters get cleaned up, even if subclassed.
diff --git a/dalvikvm/Android.mk b/dalvikvm/Android.mk
index 216d08e..f463c85 100644
--- a/dalvikvm/Android.mk
+++ b/dalvikvm/Android.mk
@@ -14,20 +14,61 @@
LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= \
+#
+# Common definitions.
+#
+
+dalvikvm_src_files := \
Main.c
-LOCAL_C_INCLUDES := \
- $(JNI_H_INCLUDE) \
- dalvik/include
+dalvikvm_c_includes := \
+ $(JNI_H_INCLUDE) \
+ dalvik/include
+
+
+#
+# Build for the target (device).
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(dalvikvm_src_files)
+LOCAL_C_INCLUDES := $(dalvikvm_c_includes)
LOCAL_SHARED_LIBRARIES := \
- libdvm \
- libssl \
- libz
+ libdvm \
+ libssl \
+ libz
-LOCAL_MODULE:= dalvikvm
+LOCAL_MODULE := dalvikvm
include $(BUILD_EXECUTABLE)
+
+
+#
+# Build for the host.
+#
+
+ifeq ($(WITH_HOST_DALVIK),true)
+
+ include $(CLEAR_VARS)
+
+ LOCAL_SRC_FILES := $(dalvikvm_src_files)
+ LOCAL_C_INCLUDES := $(dalvikvm_c_includes)
+
+ LOCAL_STATIC_LIBRARIES := \
+ libdvm-host
+
+ ifeq ($(HOST_OS)-$(HOST_ARCH),darwin-x86)
+ # OSX comes with libz and libssl, so there is no need to build them.
+ LOCAL_LDLIBS := -lssl -lz
+ else
+ LOCAL_STATIC_LIBRARIES += libssl libz
+ endif
+
+ LOCAL_MODULE := dalvikvm-host
+
+ include $(BUILD_HOST_EXECUTABLE)
+
+endif
diff --git a/dexopt/Android.mk b/dexopt/Android.mk
index 8e30a2c..8637073 100644
--- a/dexopt/Android.mk
+++ b/dexopt/Android.mk
@@ -29,6 +29,8 @@
$(JNI_H_INCLUDE)
LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ liblog \
libz \
libssl \
libdvm
diff --git a/docs/jni-tips.html b/docs/jni-tips.html
index e85434b..56136e8 100644
--- a/docs/jni-tips.html
+++ b/docs/jni-tips.html
@@ -356,7 +356,7 @@
<li>MonitorExit
<li>PopLocalFrame
<li>PushLocalFrame
- <li>Release<PrimitiveType>ArrayElements
+ <li>Release<PrimitiveType>ArrayElements
<li>ReleasePrimitiveArrayCritical
<li>ReleaseStringChars
<li>ReleaseStringCritical
diff --git a/libcore/archive/src/main/java/java/util/zip/Deflater.java b/libcore/archive/src/main/java/java/util/zip/Deflater.java
index ee9c3ea..48ae479 100644
--- a/libcore/archive/src/main/java/java/util/zip/Deflater.java
+++ b/libcore/archive/src/main/java/java/util/zip/Deflater.java
@@ -17,9 +17,6 @@
package java.util.zip;
-// BEGIN android-changed
-// import org.apache.harmony.luni.platform.OSResourcesMonitor;
-// END android-changed
/**
* This class compresses data using the <i>DEFLATE</i> algorithm (see <a
@@ -149,8 +146,7 @@
throw new IllegalArgumentException();
}
compressLevel = level;
- streamHandle = createStreamWithMemoryEnsurance(compressLevel, strategy,
- noHeader);
+ streamHandle = createStream(compressLevel, strategy, noHeader);
}
/**
@@ -502,13 +498,5 @@
return getTotalOutImpl(streamHandle);
}
- private long createStreamWithMemoryEnsurance(int level, int strategy1,
- boolean noHeader1) {
- // BEGIN android-changed
- // OSResourcesMonitor.ensurePhysicalMemoryCapacity();
- // END android-changed
- return createStream(level, strategy1, noHeader1);
- }
-
private native long createStream(int level, int strategy1, boolean noHeader1);
}
diff --git a/libcore/archive/src/main/java/java/util/zip/ZipFile.java b/libcore/archive/src/main/java/java/util/zip/ZipFile.java
index 653b2c9..b5f3678 100644
--- a/libcore/archive/src/main/java/java/util/zip/ZipFile.java
+++ b/libcore/archive/src/main/java/java/util/zip/ZipFile.java
@@ -52,12 +52,12 @@
File fileToDeleteOnClose;
/**
- * Open zip file for read.
+ * Open ZIP file for read.
*/
public static final int OPEN_READ = 1;
/**
- * Delete zip file when closed.
+ * Delete ZIP file when closed.
*/
public static final int OPEN_DELETE = 4;
@@ -140,7 +140,7 @@
}
/**
- * Closes this ZIP file.
+ * Closes this ZIP file. This method is idempotent.
*
* @throws IOException
* if an IOException occurs.
@@ -166,23 +166,32 @@
}
}
+ private void checkNotClosed() {
+ if (mRaf == null) {
+ throw new IllegalStateException("Zip File closed.");
+ }
+ }
+
/**
* Returns an enumeration of the entries. The entries are listed in the
* order in which they appear in the ZIP archive.
*
* @return the enumeration of the entries.
+ * @throws IllegalStateException if this ZIP file has been closed.
*/
public Enumeration<? extends ZipEntry> entries() {
+ checkNotClosed();
+
return new Enumeration<ZipEntry>() {
private int i = 0;
public boolean hasMoreElements() {
- if (mRaf == null) throw new IllegalStateException("Zip File closed.");
+ checkNotClosed();
return i < mEntryList.size();
}
public ZipEntry nextElement() {
- if (mRaf == null) throw new IllegalStateException("Zip File closed.");
+ checkNotClosed();
if (i >= mEntryList.size())
throw new NoSuchElementException();
return (ZipEntry) mEntryList.get(i++);
@@ -197,8 +206,10 @@
* the name of the entry in the ZIP file.
* @return a {@code ZipEntry} or {@code null} if the entry name does not
* exist in the ZIP file.
+ * @throws IllegalStateException if this ZIP file has been closed.
*/
public ZipEntry getEntry(String entryName) {
+ checkNotClosed();
if (entryName != null) {
ZipEntry ze = mFastLookup.get(entryName);
if (ze == null) ze = mFastLookup.get(entryName + "/");
@@ -215,6 +226,7 @@
* @return an input stream of the data contained in the {@code ZipEntry}.
* @throws IOException
* if an {@code IOException} occurs.
+ * @throws IllegalStateException if this ZIP file has been closed.
*/
public InputStream getInputStream(ZipEntry entry) throws IOException {
/*
@@ -229,27 +241,25 @@
* Create a ZipInputStream at the right part of the file.
*/
RandomAccessFile raf = mRaf;
- if (raf != null) {
- synchronized (raf) {
- // Unfortunately we don't know the entry data's start position.
- // All we have is the position of the entry's local header.
- // At position 28 we find the length of the extra data.
- // In some cases this length differs from the one coming in
- // the central header!!!
- RAFStream rafstrm = new RAFStream(raf, entry.mLocalHeaderRelOffset + 28);
- int localExtraLenOrWhatever = ler.readShortLE(rafstrm);
- // Now we need to skip the name
- // and this "extra" data or whatever it is:
- rafstrm.skip(entry.nameLen + localExtraLenOrWhatever);
- rafstrm.mLength = rafstrm.mOffset + entry.compressedSize;
- if (entry.compressionMethod == ZipEntry.DEFLATED) {
- return new InflaterInputStream(rafstrm, new Inflater(true));
- } else {
- return rafstrm;
- }
+ synchronized (raf) {
+ // Unfortunately we don't know the entry data's start position.
+ // All we have is the position of the entry's local header.
+ // At position 28 we find the length of the extra data.
+ // In some cases this length differs from the one coming in
+ // the central header!!!
+ RAFStream rafstrm = new RAFStream(raf,
+ entry.mLocalHeaderRelOffset + 28);
+ int localExtraLenOrWhatever = ler.readShortLE(rafstrm);
+ // Now we need to skip the name
+ // and this "extra" data or whatever it is:
+ rafstrm.skip(entry.nameLen + localExtraLenOrWhatever);
+ rafstrm.mLength = rafstrm.mOffset + entry.compressedSize;
+ if (entry.compressionMethod == ZipEntry.DEFLATED) {
+ return new InflaterInputStream(rafstrm, new Inflater(true));
+ } else {
+ return rafstrm;
}
}
- throw new IllegalStateException("Zip File closed");
}
/**
@@ -265,8 +275,10 @@
* Returns the number of {@code ZipEntries} in this {@code ZipFile}.
*
* @return the number of entries in this file.
+ * @throws IllegalStateException if this ZIP file has been closed.
*/
public int size() {
+ checkNotClosed();
return mEntryList.size();
}
diff --git a/libcore/archive/src/main/native/java_util_zip_Adler32.c b/libcore/archive/src/main/native/java_util_zip_Adler32.c
index 1b02a11..0fcf549 100644
--- a/libcore/archive/src/main/native/java_util_zip_Adler32.c
+++ b/libcore/archive/src/main/native/java_util_zip_Adler32.c
@@ -25,16 +25,11 @@
jbyteArray buf, int off, int len,
jlong crc)
{
- jbyte *b;
- jboolean isCopy;
- jlong result;
-
- b = (*env)->GetPrimitiveArrayCritical (env, buf, &isCopy);
+ jbyte* b = (*env)->GetPrimitiveArrayCritical (env, buf, NULL);
if (b == NULL) {
- throwNewOutOfMemoryError(env, "");
return 0;
}
- result = (jlong) adler32 ((uLong) crc, (Bytef *) (b + off), (uInt) len);
+ jlong result = (jlong) adler32 ((uLong) crc, (Bytef *) (b + off), (uInt) len);
(*env)->ReleasePrimitiveArrayCritical (env, buf, b, JNI_ABORT);
return result;
diff --git a/libcore/archive/src/main/native/java_util_zip_CRC32.c b/libcore/archive/src/main/native/java_util_zip_CRC32.c
index cee25e5..fe50fca 100644
--- a/libcore/archive/src/main/native/java_util_zip_CRC32.c
+++ b/libcore/archive/src/main/native/java_util_zip_CRC32.c
@@ -25,15 +25,11 @@
jbyteArray buf, int off, int len,
jlong crc)
{
- jbyte *b;
- jlong result;
-
- b = ((*env)->GetPrimitiveArrayCritical (env, buf, 0));
+ jbyte* b = ((*env)->GetPrimitiveArrayCritical (env, buf, 0));
if (b == NULL) {
- throwNewOutOfMemoryError(env, "");
return -1;
}
- result = crc32 ((uLong) crc, (Bytef *) (b + off), (uInt) len);
+ jlong result = crc32 ((uLong) crc, (Bytef *) (b + off), (uInt) len);
((*env)->ReleasePrimitiveArrayCritical (env, buf, b, JNI_ABORT));
return result;
}
diff --git a/libcore/archive/src/main/native/java_util_zip_Deflater.c b/libcore/archive/src/main/native/java_util_zip_Deflater.c
index 2e0e268..af0bfcc 100644
--- a/libcore/archive/src/main/native/java_util_zip_Deflater.c
+++ b/libcore/archive/src/main/native/java_util_zip_Deflater.c
@@ -162,29 +162,19 @@
{
PORT_ACCESS_FROM_ENV (env);
- jbyte *in;
- JCLZipStream *stream;
-
- stream = (JCLZipStream *) ((IDATA) handle);
- if (stream->inaddr != NULL) /*Input has already been provided, free the old buffer */
+ JCLZipStream* stream = (JCLZipStream *) ((IDATA) handle);
+ if (stream->inaddr != NULL) {
+ /* Input has already been provided, free the old buffer. */
jclmem_free_memory (env, stream->inaddr);
+ }
stream->inaddr = jclmem_allocate_memory (env, len);
- if (stream->inaddr == NULL)
- {
- throwNewOutOfMemoryError (env, "");
- return;
- }
- in = ((*env)->GetPrimitiveArrayCritical (env, buf, 0));
- if (in == NULL) {
- throwNewOutOfMemoryError(env, "");
+ if (stream->inaddr == NULL) {
+ throwNewOutOfMemoryError (env, "");
return;
}
- memcpy (stream->inaddr, (in + off), len);
- ((*env)->ReleasePrimitiveArrayCritical (env, buf, in, JNI_ABORT));
+ (*env)->GetByteArrayRegion(env, buf, off, len, (jbyte*) stream->inaddr);
stream->stream->next_in = (Bytef *) stream->inaddr;
stream->stream->avail_in = len;
-
- return;
}
JNIEXPORT jint JNICALL
@@ -209,7 +199,6 @@
sout = stream->stream->total_out;
out = ((*env)->GetPrimitiveArrayCritical (env, buf, 0));
if (out == NULL) {
- throwNewOutOfMemoryError(env, "");
return -1;
}
stream->stream->next_out = (Bytef *) out + off;
diff --git a/libcore/archive/src/main/native/java_util_zip_Inflater.c b/libcore/archive/src/main/native/java_util_zip_Inflater.c
index 4b30d4e..c04a223 100644
--- a/libcore/archive/src/main/native/java_util_zip_Inflater.c
+++ b/libcore/archive/src/main/native/java_util_zip_Inflater.c
@@ -104,29 +104,20 @@
{
PORT_ACCESS_FROM_ENV (env);
- jbyte *in;
- U_8 *baseAddr;
JCLZipStream *stream = (JCLZipStream *) ((IDATA) handle);
-
- if (stream->inaddr != NULL) /*Input has already been provided, free the old buffer */
+ if (stream->inaddr != NULL) {
+ /* Input has already been provided, free the old buffer. */
jclmem_free_memory (env, stream->inaddr);
- baseAddr = jclmem_allocate_memory (env, len);
- if (baseAddr == NULL)
- {
- throwNewOutOfMemoryError (env, "");
- return;
- }
+ }
+ U_8* baseAddr = jclmem_allocate_memory (env, len);
+ if (baseAddr == NULL) {
+ throwNewOutOfMemoryError (env, "");
+ return;
+ }
stream->inaddr = baseAddr;
stream->stream->next_in = (Bytef *) baseAddr;
stream->stream->avail_in = len;
- in = ((*env)->GetPrimitiveArrayCritical (env, buf, 0));
- if (in == NULL) {
- throwNewOutOfMemoryError(env, "");
- return;
- }
- memcpy (baseAddr, (in + off), len);
- ((*env)->ReleasePrimitiveArrayCritical (env, buf, in, JNI_ABORT));
- return;
+ (*env)->GetByteArrayRegion(env, buf, off, len, (jbyte*) baseAddr);
}
JNIEXPORT jint JNICALL
diff --git a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/DalvikExecTest.java b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/DalvikExecTest.java
index 77fbb15..601fe42 100644
--- a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/DalvikExecTest.java
+++ b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/DalvikExecTest.java
@@ -21,10 +21,8 @@
import dalvik.annotation.TestTargetClass;
import dalvik.annotation.TestTargetNew;
import dalvik.annotation.TestTargets;
-
import junit.framework.TestCase;
-
-import tests.support.Support_Exec;
+import static tests.support.Support_Exec.execAndGetOutput;
import tests.support.resource.Support_Resources;
import java.io.ByteArrayOutputStream;
@@ -32,49 +30,47 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.util.ArrayList;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
-import java.util.jar.JarFile;
@TestTargetClass(JarOutputStream.class)
@AndroidOnly("dalvik vm specific")
public class DalvikExecTest extends TestCase {
- String execDalvik1 (String classpath, String mainClass, String arg1)
+ String execDalvik1(String classpath, String mainClass, String arg1)
throws IOException, InterruptedException {
- ArrayList<String> cmdLine = new ArrayList<String>(10);
+ ProcessBuilder builder = new ProcessBuilder();
String base = System.getenv("OUT");
- cmdLine.add(base + "/system/bin/dalvikvm");
+ builder.command().add(base + "/system/bin/dalvikvm");
- cmdLine.add("-Djava.io.tmpdir=/tmp/mc");
- cmdLine.add("-Duser.language=en");
- cmdLine.add("-Duser.region=US");
+ builder.command().add("-Djava.io.tmpdir=/tmp/mc");
+ builder.command().add("-Duser.language=en");
+ builder.command().add("-Duser.region=US");
if ("true".equals(System.getenv("TARGET_SIMULATOR"))) {
// Test against SIMULATOR:
// cmdLine.add("-Xmx512M");
// cmdLine.add("-Xcheck:jni");
- cmdLine.add("-Xbootclasspath:" + System.getProperty("java.boot.class.path"));
+ builder.command().add("-Xbootclasspath:" + System.getProperty("java.boot.class.path"));
} else {
// Test against EMULATOR:
}
- cmdLine.add("-classpath");
- cmdLine.add(classpath);
- cmdLine.add(mainClass);
+ builder.command().add("-classpath");
+ builder.command().add(classpath);
+ builder.command().add(mainClass);
- if (arg1 != null) cmdLine.add(arg1);
+ if (arg1 != null) {
+ builder.command().add(arg1);
+ }
- Object[] res = Support_Exec.execAndDigestOutput(
- cmdLine.toArray(new String[cmdLine.size()]),
- null );
- return Support_Exec.getProcessOutput(res, true);
+ return execAndGetOutput(builder);
}
String execDalvik (String classpath, String mainClass)
diff --git a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarExecTest.java b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarExecTest.java
index 4c209d1..01f5a8c 100644
--- a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarExecTest.java
+++ b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarExecTest.java
@@ -21,7 +21,8 @@
import dalvik.annotation.TestLevel;
import dalvik.annotation.TestTargetClass;
import dalvik.annotation.TestTargetNew;
-import tests.support.Support_Exec;
+import static tests.support.Support_Exec.execAndGetOutput;
+import static tests.support.Support_Exec.javaProcessBuilder;
import tests.support.resource.Support_Resources;
import java.io.File;
@@ -73,15 +74,12 @@
jout.close();
-
- // set up the VM parameters
- String[] args = new String[] {"-jar", outputJar.getAbsolutePath()};
-
// execute the JAR and read the result
- String res = Support_Exec.execJava(args, null, false);
-
- assertTrue("Error executing JAR : result returned was incorrect.", res
- .startsWith("FOOBAR"));
+ ProcessBuilder builder = javaProcessBuilder();
+ builder.command().add("-jar");
+ builder.command().add(outputJar.getAbsolutePath());
+ assertTrue("Error executing JAR",
+ execAndGetOutput(builder).startsWith("FOOBAR"));
}
/**
@@ -123,13 +121,12 @@
joutBar.write(getResource(resources, "hyts_Bar.ser"));
joutBar.close();
- String[] args = new String[] {"-jar", fooJar.getAbsolutePath()};
-
// execute the JAR and read the result
- String res = Support_Exec.execJava(args, null, false);
-
- assertTrue("Error executing JAR : result returned was incorrect.", res
- .startsWith("FOOBAR"));
+ ProcessBuilder builder = javaProcessBuilder();
+ builder.command().add("-jar");
+ builder.command().add(fooJar.getAbsolutePath());
+ assertTrue("Error executing JAR",
+ execAndGetOutput(builder).startsWith("FOOBAR"));
// rewrite manifest so it contains not only reference to bar but useless
// entries as well
@@ -139,10 +136,8 @@
joutFoo.write(getResource(resources, "hyts_Foo.ser"));
joutFoo.close();
// execute the JAR and read the result
- res = Support_Exec.execJava(args, null, false);
- assertTrue("Error executing JAR : result returned was incorrect.", res
- .startsWith("FOOBAR"));
-
+ assertTrue("Error executing JAR",
+ execAndGetOutput(builder).startsWith( "FOOBAR"));
// play with relative file names - put relative path as ../<parent dir
// name>/xx.jar
@@ -154,9 +149,8 @@
joutFoo.write(getResource(resources, "hyts_Foo.ser"));
joutFoo.close();
// execute the JAR and read the result
- res = Support_Exec.execJava(args, null, false);
- assertTrue("Error executing JAR : result returned was incorrect.", res
- .startsWith("FOOBAR"));
+ assertTrue("Error executing JAR",
+ execAndGetOutput(builder).startsWith( "FOOBAR"));
}
/**
@@ -199,13 +193,12 @@
joutBar.write(getResource(resources, "hyts_Bar.ser"));
joutBar.close();
- String[] args = new String[] {"-jar", barJar.getAbsolutePath()};
-
// execute the JAR and read the result
- String res = Support_Exec.execJava(args, null, false);
-
- assertTrue("Error executing JAR : result returned was incorrect.", res
- .startsWith("FOOBAR"));
+ ProcessBuilder builder = javaProcessBuilder();
+ builder.command().add("-jar");
+ builder.command().add(barJar.getAbsolutePath());
+ assertTrue("Error executing JAR",
+ execAndGetOutput(builder).startsWith("FOOBAR"));
}
@TestTargetNew(
@@ -229,15 +222,13 @@
joutFoo.write(getResource(resources, "hyts_Bar.ser"));
joutFoo.close();
- String[] args = new String[] {"foo.bar.execjartest.Foo"};
-
// execute the JAR and read the result
- String res = Support_Exec.execJava(args, null,
- new String[] {"CLASSPATH=" + fooJar.getAbsolutePath()}, false);
+ ProcessBuilder builder = javaProcessBuilder();
+ builder.environment().put("CLASSPATH", fooJar.getAbsolutePath());
+ builder.command().add("foo.bar.execjartest.Foo");
- assertTrue(
- "Error executing class from ClassPath : result returned was incorrect.",
- res.startsWith("FOOBAR"));
+ assertTrue("Error executing class from ClassPath",
+ execAndGetOutput(builder).startsWith("FOOBAR"));
// ok - next try - add -cp to path - it should override env
File booJar = File.createTempFile("hyts_", ".jar");
@@ -257,13 +248,14 @@
joutBoo.write(farBody.getBytes("iso-8859-1"));
joutBoo.close();
- res = Support_Exec.execJava(args, new String[] {booJar
- .getAbsolutePath()}, new String[] {"CLASSPATH="
- + fooJar.getAbsolutePath()}, false);
+ builder = javaProcessBuilder();
+ builder.environment().put("CLASSPATH", fooJar.getAbsolutePath());
+ builder.command().add("-cp");
+ builder.command().add(booJar.getAbsolutePath());
+ builder.command().add("foo.bar.execjartest.Foo");
- assertTrue(
- "Error executing class specified by -cp : result returned was incorrect.",
- res.startsWith("BOOFAR"));
+ assertTrue("Error executing class specified by -cp",
+ execAndGetOutput(builder).startsWith("BOOFAR"));
// now add -jar option - it should override env and classpath
Manifest man = new Manifest();
@@ -288,15 +280,15 @@
joutZoo.write(zarBody.getBytes("iso-8859-1"));
joutZoo.close();
- args = new String[] {"-jar", zooJar.getAbsolutePath()};
+ builder = javaProcessBuilder();
+ builder.environment().put("CLASSPATH", fooJar.getAbsolutePath());
+ builder.command().add("-cp");
+ builder.command().add(booJar.getAbsolutePath());
+ builder.command().add("-jar");
+ builder.command().add(zooJar.getAbsolutePath());
- res = Support_Exec.execJava(args, new String[] {booJar
- .getAbsolutePath()}, new String[] {"CLASSPATH="
- + fooJar.getAbsolutePath()}, false);
-
- assertTrue(
- "Error executing class specified by -cp : result returned was incorrect.",
- res.startsWith("ZOOZAR"));
+ assertTrue("Error executing class specified by -jar",
+ execAndGetOutput(builder).startsWith("ZOOZAR"));
}
private static byte[] getResource(File tempDir, String resourceName)
diff --git a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarOutputStreamTest.java b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarOutputStreamTest.java
index acdad71..b2ecdec 100644
--- a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarOutputStreamTest.java
+++ b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarOutputStreamTest.java
@@ -34,7 +34,6 @@
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
-import tests.support.Support_Exec;
import tests.support.resource.Support_Resources;
@TestTargetClass(JarOutputStream.class)
diff --git a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/ZipExecTest.java b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/ZipExecTest.java
index c6f07de..013974c 100644
--- a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/ZipExecTest.java
+++ b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/ZipExecTest.java
@@ -21,7 +21,8 @@
import dalvik.annotation.TestLevel;
import dalvik.annotation.TestTargetClass;
import dalvik.annotation.TestTargetNew;
-import tests.support.Support_Exec;
+import static tests.support.Support_Exec.javaProcessBuilder;
+import static tests.support.Support_Exec.execAndGetOutput;
import tests.support.resource.Support_Resources;
import java.io.File;
@@ -72,15 +73,12 @@
man.write(zout);
zout.close();
+ ProcessBuilder builder = javaProcessBuilder();
+ builder.command().add("-jar");
+ builder.command().add(outputZip.getAbsolutePath());
- // set up the VM parameters
- String[] args = new String[] {"-jar", outputZip.getAbsolutePath()};
-
- // execute the JAR and read the result
- String res = Support_Exec.execJava(args, null, false);
-
- assertTrue("Error executing ZIP : result returned was incorrect.", res
- .startsWith("FOOBAR"));
+ assertTrue("Error executing ZIP",
+ execAndGetOutput(builder).startsWith("FOOBAR"));
}
/**
@@ -124,13 +122,12 @@
zoutBar.write(getResource(resources, "hyts_Bar.ser"));
zoutBar.close();
- String[] args = new String[] {"-jar", fooZip.getAbsolutePath()};
-
// execute the JAR and read the result
- String res = Support_Exec.execJava(args, null, false);
-
- assertTrue("Error executing JAR : result returned was incorrect.", res
- .startsWith("FOOBAR"));
+ ProcessBuilder builder = javaProcessBuilder();
+ builder.command().add("-jar");
+ builder.command().add(fooZip.getAbsolutePath());
+ assertTrue("Error executing JAR",
+ execAndGetOutput(builder).startsWith( "FOOBAR"));
// rewrite manifest so it contains not only reference to bar but useless
// entries as well
@@ -142,9 +139,8 @@
zoutFoo.write(getResource(resources, "hyts_Foo.ser"));
zoutFoo.close();
// execute the JAR and read the result
- res = Support_Exec.execJava(args, null, false);
- assertTrue("Error executing JAR : result returned was incorrect.", res
- .startsWith("FOOBAR"));
+ assertTrue("Error executing JAR",
+ execAndGetOutput(builder).startsWith("FOOBAR"));
// play with relative file names - put relative path as ../<parent dir
@@ -159,9 +155,8 @@
zoutFoo.write(getResource(resources, "hyts_Foo.ser"));
zoutFoo.close();
// execute the ZIP and read the result
- res = Support_Exec.execJava(args, null, false);
- assertTrue("Error executing JAR : result returned was incorrect.", res
- .startsWith("FOOBAR"));
+ assertTrue("Error executing JAR",
+ execAndGetOutput(builder).startsWith("FOOBAR"));
}
@@ -199,13 +194,11 @@
zoutBar.write(getResource(resources, "hyts_Bar.ser"));
zoutBar.close();
- String[] args = new String[] {"-jar", fooJar.getAbsolutePath()};
-
- // execute the JAR and read the result
- String res = Support_Exec.execJava(args, null, false);
-
- assertTrue("Error executing JAR : result returned was incorrect.", res
- .startsWith("FOOBAR"));
+ ProcessBuilder builder = javaProcessBuilder();
+ builder.command().add("-jar");
+ builder.command().add(fooJar.getAbsolutePath());
+ assertTrue("Error executing JAR",
+ execAndGetOutput(builder).startsWith("FOOBAR"));
}
@TestTargetNew(
@@ -244,13 +237,12 @@
joutBar.write(getResource(resources, "hyts_Bar.ser"));
joutBar.close();
- String[] args = new String[] {"-jar", fooZip.getAbsolutePath()};
-
// execute the JAR and read the result
- String res = Support_Exec.execJava(args, null, false);
-
- assertTrue("Error executing ZIP : result returned was incorrect.", res
- .startsWith("FOOBAR"));
+ ProcessBuilder builder = javaProcessBuilder();
+ builder.command().add("-jar");
+ builder.command().add(fooZip.getAbsolutePath());
+ assertTrue("Error executing ZIP",
+ execAndGetOutput(builder).startsWith("FOOBAR"));
}
/**
@@ -296,13 +288,12 @@
zoutBar.write(getResource(resources, "hyts_Bar.ser"));
zoutBar.close();
- String[] args = new String[] {"-jar", barZip.getAbsolutePath()};
-
// execute the JAR and read the result
- String res = Support_Exec.execJava(args, null, false);
-
- assertTrue("Error executing JAR : result returned was incorrect.", res
- .startsWith("FOOBAR"));
+ ProcessBuilder builder = javaProcessBuilder();
+ builder.command().add("-jar");
+ builder.command().add(barZip.getAbsolutePath());
+ assertTrue("Error executing JAR",
+ execAndGetOutput(builder).startsWith("FOOBAR"));
}
diff --git a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipFileTest.java b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipFileTest.java
index b025e11..146c679 100644
--- a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipFileTest.java
+++ b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipFileTest.java
@@ -271,14 +271,23 @@
Enumeration<? extends ZipEntry> enumeration = zfile.entries();
zfile.close();
- zfile = null;
- boolean pass = false;
+ try {
+ enumeration.nextElement();
+ fail("did not detect closed file");
+ } catch (IllegalStateException expected) {
+ }
+
try {
enumeration.hasMoreElements();
- } catch (IllegalStateException e) {
- pass = true;
+ fail("did not detect closed file");
+ } catch (IllegalStateException expected) {
}
- assertTrue("did not detect closed jar file", pass);
+
+ try {
+ zfile.entries();
+ fail("did not detect closed file");
+ } catch (IllegalStateException expected) {
+ }
}
/**
@@ -349,20 +358,15 @@
method = "getEntry",
args = {java.lang.String.class}
)
- @KnownFailure("Android does not throw IllegalStateException when using "
- + "getEntry() after close().")
public void test_getEntryLjava_lang_String_Ex() throws IOException {
java.util.zip.ZipEntry zentry = zfile.getEntry("File1.txt");
assertNotNull("Could not obtain ZipEntry", zentry);
- int r;
- InputStream in;
zfile.close();
try {
- zentry = zfile.getEntry("File2.txt");
- fail("IllegalStateException expected"); // Android fails here!
+ zfile.getEntry("File2.txt");
+ fail("IllegalStateException expected");
} catch (IllegalStateException ee) {
- // expected
}
}
@@ -435,16 +439,13 @@
method = "size",
args = {}
)
- @KnownFailure("IllegalStateException not thrown when using ZipFile.size() "
- + "after close().")
public void test_size() throws IOException {
assertEquals(6, zfile.size());
zfile.close();
try {
zfile.size();
- fail("IllegalStateException expected"); // Android fails here!
- } catch (IllegalStateException ee) {
- // expected
+ fail("IllegalStateException expected");
+ } catch (IllegalStateException expected) {
}
}
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
index ee21b13..312c76d 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
@@ -30,7 +30,10 @@
private long rawIndex(int i) {
if (i < 0 || i >= array.length)
throw new IndexOutOfBoundsException("index " + i);
- return base + i * scale;
+ // BEGIN android-changed
+ // avoid memory corruption
+ return base + (long) i * scale;
+ // END android-changed
}
/**
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
index d96f4c2..187acbc 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
@@ -29,7 +29,10 @@
private long rawIndex(int i) {
if (i < 0 || i >= array.length)
throw new IndexOutOfBoundsException("index " + i);
- return base + i * scale;
+ // BEGIN android-changed
+ // avoid memory corruption
+ return base + (long) i * scale;
+ // END android-changed
}
/**
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java
index 9a484e6..fff6a1e 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java
@@ -30,7 +30,10 @@
private long rawIndex(int i) {
if (i < 0 || i >= array.length)
throw new IndexOutOfBoundsException("index " + i);
- return base + i * scale;
+ // BEGIN android-changed
+ // avoid memory corruption
+ return base + (long) i * scale;
+ // END android-changed
}
/**
diff --git a/libcore/dalvik/src/main/java/dalvik/system/DexClassLoader.java b/libcore/dalvik/src/main/java/dalvik/system/DexClassLoader.java
index 73e6fe4..4a440b5 100644
--- a/libcore/dalvik/src/main/java/dalvik/system/DexClassLoader.java
+++ b/libcore/dalvik/src/main/java/dalvik/system/DexClassLoader.java
@@ -114,7 +114,7 @@
/* open all Zip and DEX files up front */
for (int i = 0; i < length; i++) {
- System.out.println("My path is: " + dexPathList[i]);
+ //System.out.println("My path is: " + dexPathList[i]);
File pathFile = new File(dexPathList[i]);
mFiles[i] = pathFile;
diff --git a/libcore/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormat.java b/libcore/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormat.java
index 5bee1fd..104336e 100644
--- a/libcore/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormat.java
+++ b/libcore/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormat.java
@@ -48,6 +48,13 @@
private boolean posPrefNull;
private boolean posSuffNull;
+ /**
+ * Cache the BigDecimal form of the multiplier. This is null until we've
+ * formatted a BigDecimal (with a multipler that is not 1), or the user has
+ * explicitly called {@link #setMultiplier(int)} with any multiplier.
+ */
+ private transient BigDecimal multiplierBigDecimal = null;
+
public DecimalFormat(String pattern, DecimalFormatSymbols icuSymbols) {
this.addr = icuSymbols.getAddr();
this.symbols = icuSymbols;
@@ -118,6 +125,14 @@
return result;
}
+ private BigDecimal applyMultiplier(BigDecimal valBigDecimal) {
+ if (multiplierBigDecimal == null) {
+ multiplierBigDecimal = BigDecimal.valueOf(getMultiplier());
+ }
+ // Get new value by multiplying multiplier.
+ return valBigDecimal.multiply(multiplierBigDecimal);
+ }
+
@Override
public StringBuffer format(Object value, StringBuffer buffer, FieldPosition field) {
@@ -139,6 +154,9 @@
return buffer.append(result);
} else if(number instanceof BigDecimal) {
BigDecimal valBigDecimal = (BigDecimal) number;
+ if (getMultiplier() != 1) {
+ valBigDecimal = applyMultiplier(valBigDecimal);
+ }
StringBuilder val = new StringBuilder();
val.append(valBigDecimal.unscaledValue().toString(10));
int scale = valBigDecimal.scale();
@@ -233,6 +251,9 @@
valBigInteger.toString(10), null, null, attributes, 0);
} else if(number instanceof BigDecimal) {
BigDecimal valBigDecimal = (BigDecimal) number;
+ if (getMultiplier() != 1) {
+ valBigDecimal = applyMultiplier(valBigDecimal);
+ }
StringBuilder val = new StringBuilder();
val.append(valBigDecimal.unscaledValue().toString(10));
int scale = valBigDecimal.scale();
@@ -441,6 +462,8 @@
public void setMultiplier(int value) {
NativeDecimalFormat.setAttribute(this.addr,
UNumberFormatAttribute.UNUM_MULTIPLIER.ordinal(), value);
+ // Update the cached BigDecimal for multiplier.
+ multiplierBigDecimal = BigDecimal.valueOf(value);
}
public void setNegativePrefix(String value) {
diff --git a/libcore/icu/src/main/java/com/ibm/icu4jni/util/Resources.java b/libcore/icu/src/main/java/com/ibm/icu4jni/util/Resources.java
index 0460fde..086f8d4 100644
--- a/libcore/icu/src/main/java/com/ibm/icu4jni/util/Resources.java
+++ b/libcore/icu/src/main/java/com/ibm/icu4jni/util/Resources.java
@@ -114,7 +114,7 @@
isoLanguages = getISOLanguagesNative();
}
- return isoLanguages;
+ return isoLanguages.clone();
}
/**
@@ -128,7 +128,7 @@
isoCountries = getISOCountriesNative();
}
- return isoCountries;
+ return isoCountries.clone();
}
/**
@@ -142,7 +142,7 @@
availableLocales = getAvailableLocalesNative();
}
- return availableLocales;
+ return availableLocales.clone();
}
/**
@@ -157,7 +157,7 @@
availableTimezones = TimeZone.getAvailableIDs();
}
- return availableTimezones;
+ return availableTimezones.clone();
}
/**
@@ -264,17 +264,25 @@
if (locale == null) {
locale = defaultLocale;
}
-
+
// If locale == default and the default locale hasn't changed since
// DefaultTimeZones loaded, return the cached names.
// TODO: We should force a reboot if the default locale changes.
if (defaultLocale.equals(locale) && DefaultTimeZones.locale.equals(defaultLocale)) {
- return DefaultTimeZones.names;
+ return clone2dStringArray(DefaultTimeZones.names);
}
return createTimeZoneNamesFor(locale);
}
+ private static String[][] clone2dStringArray(String[][] array) {
+ String[][] result = new String[array.length][];
+ for (int i = 0; i < array.length; ++i) {
+ result[i] = array[i].clone();
+ }
+ return result;
+ }
+
// --- Specialized ResourceBundle subclasses ------------------------------
/**
diff --git a/libcore/icu/src/main/native/BidiWrapperInterface.c b/libcore/icu/src/main/native/BidiWrapperInterface.c
index 2c6b3cd..19ac520 100644
--- a/libcore/icu/src/main/native/BidiWrapperInterface.c
+++ b/libcore/icu/src/main/native/BidiWrapperInterface.c
@@ -15,18 +15,17 @@
* limitations under the License.
*/
-#include <stdlib.h>
-#include <unicode/ubidi.h>
-#include <string.h>
#include "BidiWrapperInterface.h"
+#include "ErrorCode.h"
+#include "unicode/ubidi.h"
+#include <stdlib.h>
+#include <string.h>
typedef struct {
UBiDi *pBiDi;
void *embeddingLevels;
} BiDiData;
-void check_fail (JNIEnv * env, int err);
-
JNIEXPORT jlong JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1open
(JNIEnv * env, jclass clazz)
{
@@ -43,62 +42,52 @@
ubidi_close ((*data).pBiDi);
- if ((*data).embeddingLevels != NULL)
- free((*data).embeddingLevels);
- free(data);
+ free((*data).embeddingLevels);
+ free(data);
}
JNIEXPORT void JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1setPara
(JNIEnv * env, jclass clazz, jlong pBiDi, jcharArray text, jint length,
- jbyte paraLevel, jbyteArray embeddingLevels)
+ jbyte paraLevel, jbyteArray newEmbeddingLevels)
{
- UErrorCode err = 0;
- jchar *_text = NULL;
BiDiData *data = (BiDiData *)pBiDi;
- /* Remembering old embedding levels */
- void *embLvls = (*data).embeddingLevels;
-
- _text = (*env)->GetCharArrayElements (env, text, NULL);
+ void *oldEmbeddingLevels = (*data).embeddingLevels;
- if (embeddingLevels != NULL)
- {
- jbyte *el = (*env)->GetByteArrayElements (env, embeddingLevels, NULL);
- (*data).embeddingLevels = malloc(length);
- memcpy(((*data).embeddingLevels), el, length);
- (*env)->ReleaseByteArrayElements (env, embeddingLevels, el, 0);
- } else
- {
- (*data).embeddingLevels = NULL;
- }
-
- ubidi_setPara ((*data).pBiDi, _text, length, paraLevel,
- ((*data).embeddingLevels), &err);
- check_fail (env, err);
-
- /* Freeing old embedding levels */
- if (embLvls != NULL) {
- free(embLvls);
+ // Copy the new embedding levels from the Java heap to the native heap.
+ if (newEmbeddingLevels != NULL) {
+ (*data).embeddingLevels = malloc(length);
+ (*env)->GetByteArrayRegion(env, newEmbeddingLevels, 0, length,
+ (*data).embeddingLevels);
+ } else {
+ (*data).embeddingLevels = NULL;
}
+ UErrorCode err = 0;
+ jchar* _text = (*env)->GetCharArrayElements(env, text, NULL);
+ ubidi_setPara ((*data).pBiDi, _text, length, paraLevel,
+ ((*data).embeddingLevels), &err);
(*env)->ReleaseCharArrayElements (env, text, _text, 0);
+ free(oldEmbeddingLevels);
+
+ icu4jni_error(env, err);
}
JNIEXPORT jlong JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1setLine
(JNIEnv * env, jclass clazz, jlong pBiDi, jint start, jint limit)
{
- UErrorCode err = 0;
- BiDiData *data = (BiDiData *)pBiDi;
- BiDiData *lineData = (BiDiData *) malloc(sizeof(BiDiData));
- (*lineData).embeddingLevels = NULL;
+ UErrorCode err = 0;
+ BiDiData *data = (BiDiData *)pBiDi;
+ BiDiData *lineData = (BiDiData *) malloc(sizeof(BiDiData));
+ (*lineData).embeddingLevels = NULL;
- (*lineData).pBiDi = ubidi_openSized (limit - start, 0, &err);
- check_fail (env, err);
+ (*lineData).pBiDi = ubidi_openSized (limit - start, 0, &err);
+ if (icu4jni_error(env, err)) {
+ return 0;
+ }
- ubidi_setLine ((*data).pBiDi, start, limit, (*lineData).pBiDi,
- &err);
- check_fail (env, err);
-
- return (jlong) lineData;
+ ubidi_setLine ((*data).pBiDi, start, limit, (*lineData).pBiDi, &err);
+ icu4jni_error(env, err);
+ return (jlong) lineData;
}
JNIEXPORT jint JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1getDirection
@@ -125,76 +114,57 @@
JNIEXPORT jbyteArray JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1getLevels
(JNIEnv * env, jclass clazz, jlong pBiDi)
{
- UErrorCode err = 0;
- const UBiDiLevel *levels = NULL;
- jbyteArray result = NULL;
- int len = 0;
- BiDiData *data = (BiDiData *)pBiDi;
+ BiDiData *data = (BiDiData *)pBiDi;
- levels = ubidi_getLevels ((*data).pBiDi, &err);
- check_fail (env, err);
+ UErrorCode err = 0;
+ const UBiDiLevel* levels = ubidi_getLevels((*data).pBiDi, &err);
+ if (icu4jni_error(env, err)) {
+ return NULL;
+ }
- len = ubidi_getLength ((*data).pBiDi);
- result = (*env)->NewByteArray (env, len);
- (*env)->SetByteArrayRegion (env, result, 0, len, (jbyte *) levels);
+ int len = ubidi_getLength((*data).pBiDi);
+ jbyteArray result = (*env)->NewByteArray(env, len);
+ (*env)->SetByteArrayRegion(env, result, 0, len, (jbyte*) levels);
- return result;
+ return result;
}
JNIEXPORT jint JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1countRuns
(JNIEnv * env, jclass clazz, jlong pBiDi)
{
- UErrorCode err = 0;
- BiDiData *data = (BiDiData *)pBiDi;
+ BiDiData *data = (BiDiData *)pBiDi;
- int count = ubidi_countRuns ((*data).pBiDi, &err);
- check_fail (env, err);
-
- return count;
+ UErrorCode err = 0;
+ int count = ubidi_countRuns ((*data).pBiDi, &err);
+ icu4jni_error(env, err);
+ return count;
}
JNIEXPORT jobjectArray JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1getRuns
(JNIEnv * env, jclass clz, jlong pBiDi)
{
- int runCount = 0;
- int start = 0;
- int limit = 0;
- int i = 0;
- UBiDiLevel level = 0;
- jclass run_clazz = 0;
- jmethodID initID = 0;
- jobject run = 0;
- jobjectArray runs;
- UErrorCode err = 0;
- BiDiData *data = (BiDiData *)pBiDi;
+ BiDiData* data = (BiDiData*) pBiDi;
- run_clazz = (*env)->FindClass (env, "org/apache/harmony/text/BidiRun");
- initID = (*env)->GetMethodID (env, run_clazz, "<init>", "(III)V");
-
- runCount = ubidi_countRuns ((*data).pBiDi, &err);
- check_fail (env, err);
-
- runs = (*env)->NewObjectArray(env, runCount,run_clazz, NULL);
- for (i = 0; i < runCount; i++) {
- ubidi_getLogicalRun((*data).pBiDi, start, &limit, &level);
- run = (*env)->NewObject (env, run_clazz, initID, start, limit, level);
- (*env)->SetObjectArrayElement(env, runs, i, run);
- start = limit;
- }
- return runs;
-}
-
-void
-check_fail (JNIEnv * env, int err)
-{
- char message[] = "ICU Internal Error: ";
-
- if (U_FAILURE (err))
- {
- sprintf (message, "ICU Internal Error: %d", err);
- jniThrowException(env, "java/lang/RuntimeException",
- message);
+ UErrorCode err = 0;
+ int runCount = ubidi_countRuns((*data).pBiDi, &err);
+ if (icu4jni_error(env, err)) {
+ return 0;
}
+
+ jclass bidiRunClass = (*env)->FindClass(env, "org/apache/harmony/text/BidiRun");
+ jmethodID bidiRunConstructor = (*env)->GetMethodID(env, bidiRunClass, "<init>", "(III)V");
+ jobjectArray runs = (*env)->NewObjectArray(env, runCount, bidiRunClass, NULL);
+ UBiDiLevel level = 0;
+ int start = 0;
+ int limit = 0;
+ int i = 0; // TODO: switch this file to C++!
+ for (i = 0; i < runCount; ++i) {
+ ubidi_getLogicalRun((*data).pBiDi, start, &limit, &level);
+ jobject run = (*env)->NewObject(env, bidiRunClass, bidiRunConstructor, start, limit, level);
+ (*env)->SetObjectArrayElement(env, runs, i, run);
+ start = limit;
+ }
+ return runs;
}
JNIEXPORT jintArray JNICALL Java_org_apache_harmony_text_BidiWrapper_ubidi_1reorderVisual
diff --git a/libcore/icu/src/main/native/CollationInterface.c b/libcore/icu/src/main/native/CollationInterface.c
index 86246ac..c669649 100644
--- a/libcore/icu/src/main/native/CollationInterface.c
+++ b/libcore/icu/src/main/native/CollationInterface.c
@@ -172,13 +172,11 @@
static jint getNormalization(JNIEnv *env, jclass obj,
jint address) {
- UErrorCode status = U_ZERO_ERROR;
- const UCollator *collator = (const UCollator *)(int)address;
- if(U_FAILURE(status)){
- icu4jni_error(env, status);
- }
- return (jint)ucol_getAttribute(collator,UCOL_NORMALIZATION_MODE,&status);
-
+ const UCollator* collator = (const UCollator*) address;
+ UErrorCode status = U_ZERO_ERROR;
+ jint result = ucol_getAttribute(collator, UCOL_NORMALIZATION_MODE, &status);
+ icu4jni_error(env, status);
+ return result;
}
/**
@@ -192,12 +190,10 @@
static void setNormalization(JNIEnv *env, jclass obj, jint address,
jint mode) {
+ const UCollator* collator = (const UCollator*) address;
UErrorCode status = U_ZERO_ERROR;
- const UCollator *collator = (const UCollator *)(int)address;
- if(U_FAILURE(status)){
- icu4jni_error(env, status);
- }
- ucol_setAttribute(collator,UCOL_NORMALIZATION_MODE,mode,&status);
+ ucol_setAttribute(collator, UCOL_NORMALIZATION_MODE, mode, &status);
+ icu4jni_error(env, status);
}
@@ -324,12 +320,11 @@
* error has occured or if the end of string has been reached
*/
static jint next(JNIEnv *env, jclass obj, jint address) {
- UCollationElements *iterator = (UCollationElements *)(int)address;
- UErrorCode status = U_ZERO_ERROR;
- jint result = ucol_next(iterator, &status);
-
- icu4jni_error(env, status);
- return result;
+ UCollationElements *iterator = (UCollationElements *) address;
+ UErrorCode status = U_ZERO_ERROR;
+ jint result = ucol_next(iterator, &status);
+ icu4jni_error(env, status);
+ return result;
}
/**
@@ -343,14 +338,10 @@
* @exception thrown if creation of the UCollator fails
*/
static jint openCollator__(JNIEnv *env, jclass obj) {
- jint result;
- UErrorCode status = U_ZERO_ERROR;
-
- result = (jint)ucol_open(NULL, &status);
- if ( icu4jni_error(env, status) != FALSE)
- return 0;
-
- return result;
+ UErrorCode status = U_ZERO_ERROR;
+ jint result = ucol_open(NULL, &status);
+ icu4jni_error(env, status);
+ return result;
}
@@ -368,19 +359,18 @@
static jint openCollator__Ljava_lang_String_2(JNIEnv *env,
jclass obj, jstring locale) {
- /* this will be null terminated */
- const char *localestr = (*env)->GetStringUTFChars(env, locale, 0);
- jint result=0;
- UErrorCode status = U_ZERO_ERROR;
+ /* this will be null terminated */
+ const char* localeStr = (*env)->GetStringUTFChars(env, locale, NULL);
+ if (localeStr == NULL) {
+ icu4jni_error(env, U_ILLEGAL_ARGUMENT_ERROR);
+ return 0;
+ }
- if(localestr){
- result = (jint)ucol_open(localestr, &status);
- (*env)->ReleaseStringUTFChars(env, locale, localestr);
- icu4jni_error(env, status);
- }else{
- icu4jni_error(env,U_ILLEGAL_ARGUMENT_ERROR);
- }
- return result;
+ UErrorCode status = U_ZERO_ERROR;
+ jint result = ucol_open(localeStr, &status);
+ (*env)->ReleaseStringUTFChars(env, locale, localeStr);
+ icu4jni_error(env, status);
+ return result;
}
/**
@@ -586,4 +576,3 @@
return jniRegisterNativeMethods(_env, "com/ibm/icu4jni/text/NativeCollation",
gMethods, NELEM(gMethods));
}
-
diff --git a/libcore/icu/src/main/native/DecimalFormatInterface.cpp b/libcore/icu/src/main/native/DecimalFormatInterface.cpp
index 7e37d6c..f553e0a 100644
--- a/libcore/icu/src/main/native/DecimalFormatInterface.cpp
+++ b/libcore/icu/src/main/native/DecimalFormatInterface.cpp
@@ -29,33 +29,6 @@
#include <string.h>
#include "cutils/log.h"
-
-static UBool icuError(JNIEnv *env, UErrorCode errorcode)
-{
- const char *emsg = u_errorName(errorcode);
- jclass exception;
-
- if (U_FAILURE(errorcode)) {// errorcode > U_ZERO_ERROR && errorcode < U_ERROR_LIMIT) {
- switch (errorcode) {
- case U_ILLEGAL_ARGUMENT_ERROR :
- exception = env->FindClass("java/lang/IllegalArgumentException");
- break;
- case U_INDEX_OUTOFBOUNDS_ERROR :
- case U_BUFFER_OVERFLOW_ERROR :
- exception = env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
- break;
- case U_UNSUPPORTED_ERROR :
- exception = env->FindClass("java/lang/UnsupportedOperationException");
- break;
- default :
- exception = env->FindClass("java/lang/RuntimeException");
- }
-
- return (env->ThrowNew(exception, emsg) != 0);
- }
- return 0;
-}
-
static jint openDecimalFormatImpl(JNIEnv *env, jclass clazz, jstring locale,
jstring pattern) {
@@ -78,7 +51,7 @@
env->ReleaseStringUTFChars(locale, localeChars);
// check for an error
- if ( icuError(env, status) != FALSE) {
+ if (icu4jni_error(env, status) != FALSE) {
return 0;
}
@@ -115,8 +88,8 @@
// release previously allocated space
env->ReleaseStringChars(text, textChars);
- // check if an error occured
- icuError(env, status);
+ // check if an error occurred
+ icu4jni_error(env, status);
}
static jstring getSymbol(JNIEnv *env, jclass clazz, jint addr, jint symbol) {
@@ -144,7 +117,7 @@
reslenneeded=unum_getSymbol(fmt, (UNumberFormatSymbol) symbol, result,
resultlength, &status);
}
- if (icuError(env, status) != FALSE) {
+ if (icu4jni_error(env, status) != FALSE) {
return NULL;
}
@@ -189,7 +162,7 @@
env->ReleaseStringChars(text, textChars);
- icuError(env, status);
+ icu4jni_error(env, status);
}
static jstring getTextAttribute(JNIEnv *env, jclass clazz, jint addr,
@@ -219,7 +192,7 @@
(UNumberFormatTextAttribute) symbol, result, resultlength,
&status);
}
- if (icuError(env, status) != FALSE) {
+ if (icu4jni_error(env, status) != FALSE) {
return NULL;
}
@@ -246,7 +219,7 @@
env->ReleaseStringChars(pattern, pattChars);
- icuError(env, status);
+ icu4jni_error(env, status);
}
static jstring toPatternImpl(JNIEnv *env, jclass clazz, jint addr,
@@ -274,7 +247,7 @@
reslenneeded=unum_toPattern(fmt, localized, result, resultlength,
&status);
}
- if (icuError(env, status) != FALSE) {
+ if (icu4jni_error(env, status) != FALSE) {
return NULL;
}
@@ -335,7 +308,7 @@
res->extract(result, reslenneeded + 1, status);
}
- if (icuError(env, status) != FALSE) {
+ if (icu4jni_error(env, status) != FALSE) {
free(attrBuffer->buffer);
free(attrBuffer);
free(result);
@@ -444,7 +417,7 @@
res->extract(result, reslenneeded + 1, status);
}
- if (icuError(env, status) != FALSE) {
+ if (icu4jni_error(env, status) != FALSE) {
free(attrBuffer->buffer);
free(attrBuffer);
free(result);
@@ -510,7 +483,7 @@
// env->ReleaseStringUTFChars(value, valueUTF);
if (scale < 0) {
- icuError(env, U_ILLEGAL_ARGUMENT_ERROR);
+ icu4jni_error(env, U_ILLEGAL_ARGUMENT_ERROR);
return NULL;
}
@@ -532,6 +505,8 @@
const char *digits = (isPositive ? valueChars : valueChars + 1);
int length = strlen(digits);
+ DecimalFormat* fmt = reinterpret_cast<DecimalFormat*>(static_cast<uintptr_t>(addr));
+
// The length of our digit list buffer must be the actual string length + 3,
// because ICU will append some additional characters at the head and at the
// tail of the string, in order to keep strtod() happy:
@@ -551,7 +526,8 @@
digitList.fDecimalAt = digitList.fCount - scale;
digitList.fIsPositive = isPositive;
- digitList.fRoundingMode = DecimalFormat::kRoundHalfUp;
+ digitList.fRoundingMode = fmt->getRoundingMode();
+ digitList.round(fmt->getMaximumFractionDigits() + digitList.fDecimalAt);
UChar *result = NULL;
@@ -567,8 +543,6 @@
attrBuffer->bufferSize = 128;
attrBuffer->buffer = (char *) calloc(129 * sizeof(char), 1);
- DecimalFormat *fmt = (DecimalFormat *)(int)addr;
-
UnicodeString res;
fmt->subformat(res, fp, attrBuffer, digitList, isInteger);
@@ -582,7 +556,7 @@
res.extract(result, reslenneeded + 1, status);
- if (icuError(env, status) != FALSE) {
+ if (icu4jni_error(env, status) != FALSE) {
if(fieldType != NULL) {
env->ReleaseStringUTFChars(fieldType, fieldName);
}
@@ -671,28 +645,12 @@
static jobject parse(JNIEnv *env, jclass clazz, jint addr, jstring text,
jobject position) {
-
- const char * textUTF = env->GetStringUTFChars(text, NULL);
- env->ReleaseStringUTFChars(text, textUTF);
-
- const char * parsePositionClassName = "java/text/ParsePosition";
- const char * longClassName = "java/lang/Long";
- const char * doubleClassName = "java/lang/Double";
- const char * bigDecimalClassName = "java/math/BigDecimal";
- const char * bigIntegerClassName = "java/math/BigInteger";
-
- UErrorCode status = U_ZERO_ERROR;
-
- UNumberFormat *fmt = (UNumberFormat *)(int)addr;
-
- jchar *str = (UChar *)env->GetStringChars(text, NULL);
- int strlength = env->GetStringLength(text);
-
- jclass parsePositionClass = env->FindClass(parsePositionClassName);
- jclass longClass = env->FindClass(longClassName);
- jclass doubleClass = env->FindClass(doubleClassName);
- jclass bigDecimalClass = env->FindClass(bigDecimalClassName);
- jclass bigIntegerClass = env->FindClass(bigIntegerClassName);
+ // TODO: cache these?
+ jclass parsePositionClass = env->FindClass("java/text/ParsePosition");
+ jclass longClass = env->FindClass("java/lang/Long");
+ jclass doubleClass = env->FindClass("java/lang/Double");
+ jclass bigDecimalClass = env->FindClass("java/math/BigDecimal");
+ jclass bigIntegerClass = env->FindClass("java/math/BigInteger");
jmethodID getIndexMethodID = env->GetMethodID(parsePositionClass,
"getIndex", "()I");
@@ -707,27 +665,26 @@
jmethodID bigIntegerInitMethodID = env->GetMethodID(bigIntegerClass, "<init>", "(Ljava/lang/String;)V");
jmethodID doubleValueMethodID = env->GetMethodID(bigDecimalClass, "doubleValue", "()D");
- bool resultAssigned;
- int parsePos = env->CallIntMethod(position, getIndexMethodID, NULL);
-
// make sure the ParsePosition is valid. Actually icu4c would parse a number
// correctly even if the parsePosition is set to -1, but since the RI fails
// for that case we have to fail too
+ int parsePos = env->CallIntMethod(position, getIndexMethodID, NULL);
+ const int strlength = env->GetStringLength(text);
if(parsePos < 0 || parsePos > strlength) {
return NULL;
}
-
- Formattable res;
-
- const UnicodeString src((UChar*)str, strlength, strlength);
+
ParsePosition pp;
-
pp.setIndex(parsePos);
DigitList digits;
-
+
+ UNumberFormat *fmt = (UNumberFormat *)(int)addr;
+ Formattable res;
+ bool resultAssigned;
+ jchar *str = (UChar *)env->GetStringChars(text, NULL);
+ const UnicodeString src((UChar*)str, strlength, strlength);
((const DecimalFormat*)fmt)->parse(src, resultAssigned, res, pp, FALSE, digits);
-
env->ReleaseStringChars(text, str);
if(pp.getErrorIndex() == -1) {
@@ -738,20 +695,14 @@
return NULL;
}
- Formattable::Type numType;
- numType = res.getType();
+ Formattable::Type numType = res.getType();
UErrorCode fmtStatus;
double resultDouble;
long resultLong;
int64_t resultInt64;
- UnicodeString resultString;
jstring resultStr;
- int resLength;
- const char * resultUTF;
jobject resultObject1, resultObject2;
- jdouble doubleTest;
- jchar * result;
if (resultAssigned)
{
@@ -809,7 +760,7 @@
UNumberFormat *result = unum_clone(fmt, &status);
- if(icuError(env, status) != FALSE) {
+ if(icu4jni_error(env, status) != FALSE) {
return 0;
}
diff --git a/libcore/icu/src/main/native/ErrorCode.c b/libcore/icu/src/main/native/ErrorCode.c
index b3e43cd..94c4239 100644
--- a/libcore/icu/src/main/native/ErrorCode.c
+++ b/libcore/icu/src/main/native/ErrorCode.c
@@ -8,50 +8,32 @@
*/
#include "ErrorCode.h"
-
-/* private data members ----------------------------------------------------*/
+#include "JNIHelp.h"
/**
-* Name of the java runtime exception classes
-*/
-#define ILLEGALARGUMENTEXCEPTION_ "java/lang/IllegalArgumentException"
-#define ARRAYINDEXOUTOFBOUNDSEXCEPTION_ "java/lang/ArrayIndexOutOfBoundsException"
-#define UNSUPPORTEDOPERATIONEXCEPTION_ "java/lang/UnsupportedOperationException"
-#define RUNTIMEEXCEPTION_ "java/lang/RuntimeException"
-
-/* public methods ---------------------------------------------------------*/
-
-/**
-* Checks if an error has occured.
-* Throws a generic Java RuntimeException if an error has occured.
-* @param env JNI environment variable
-* @param errorcode code to determine if it is an erro
-* @return 0 if errorcode is not an error, 1 if errorcode is an error, but the
+* Checks if an error has occurred, throwing a suitable exception if so.
+* @param env JNI environment
+* @param errorCode code to determine if it is an error
+* @return 0 if errorCode is not an error, 1 if errorCode is an error, but the
* creation of the exception to be thrown fails
-* @exception thrown if errorcode represents an error
+ * @exception thrown if errorCode represents an error
*/
-UBool icu4jni_error(JNIEnv *env, UErrorCode errorcode)
+UBool icu4jni_error(JNIEnv *env, UErrorCode errorCode)
{
- const char *emsg = u_errorName(errorcode);
- jclass exception;
-
- if (errorcode > U_ZERO_ERROR && errorcode < U_ERROR_LIMIT) {
- switch (errorcode) {
- case U_ILLEGAL_ARGUMENT_ERROR :
- exception = (*env)->FindClass(env, ILLEGALARGUMENTEXCEPTION_);
- break;
- case U_INDEX_OUTOFBOUNDS_ERROR :
- case U_BUFFER_OVERFLOW_ERROR :
- exception = (*env)->FindClass(env, ARRAYINDEXOUTOFBOUNDSEXCEPTION_);
- break;
- case U_UNSUPPORTED_ERROR :
- exception = (*env)->FindClass(env, UNSUPPORTEDOPERATIONEXCEPTION_);
- break;
- default :
- exception = (*env)->FindClass(env, RUNTIMEEXCEPTION_);
+ const char* message = u_errorName(errorCode);
+ if (errorCode <= U_ZERO_ERROR || errorCode >= U_ERROR_LIMIT) {
+ return 0;
}
-
- return ((*env)->ThrowNew(env, exception, emsg) != 0);
- }
- return 0;
+
+ switch (errorCode) {
+ case U_ILLEGAL_ARGUMENT_ERROR:
+ return jniThrowException(env, "java/lang/IllegalArgumentException", message);
+ case U_INDEX_OUTOFBOUNDS_ERROR:
+ case U_BUFFER_OVERFLOW_ERROR:
+ return jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", message);
+ case U_UNSUPPORTED_ERROR:
+ return jniThrowException(env, "java/lang/UnsupportedOperationException", message);
+ default:
+ return jniThrowException(env, "java/lang/RuntimeException", message);
+ }
}
diff --git a/libcore/icu/src/main/native/ErrorCode.h b/libcore/icu/src/main/native/ErrorCode.h
index a5bbfc6..e42a519 100644
--- a/libcore/icu/src/main/native/ErrorCode.h
+++ b/libcore/icu/src/main/native/ErrorCode.h
@@ -13,6 +13,10 @@
#include "unicode/utypes.h"
#include "unicode/putil.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/**
* Checks if an error has occured.
* Throws a generic Java RuntimeException if an error has occured.
@@ -24,4 +28,8 @@
*/
UBool icu4jni_error(JNIEnv *env, UErrorCode errorcode);
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/libcore/icu/src/main/native/RBNFInterface.cpp b/libcore/icu/src/main/native/RBNFInterface.cpp
index d9bf460..c7486e1 100644
--- a/libcore/icu/src/main/native/RBNFInterface.cpp
+++ b/libcore/icu/src/main/native/RBNFInterface.cpp
@@ -25,32 +25,6 @@
#include <stdlib.h>
#include <string.h>
-static UBool icuError(JNIEnv *env, UErrorCode errorcode)
-{
- const char *emsg = u_errorName(errorcode);
- jclass exception;
-
- if (errorcode > U_ZERO_ERROR && errorcode < U_ERROR_LIMIT) {
- switch (errorcode) {
- case U_ILLEGAL_ARGUMENT_ERROR :
- exception = env->FindClass("java/lang/IllegalArgumentException");
- break;
- case U_INDEX_OUTOFBOUNDS_ERROR :
- case U_BUFFER_OVERFLOW_ERROR :
- exception = env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
- break;
- case U_UNSUPPORTED_ERROR :
- exception = env->FindClass("java/lang/UnsupportedOperationException");
- break;
- default :
- exception = env->FindClass("java/lang/RuntimeException");
- }
-
- return (env->ThrowNew(exception, emsg) != 0);
- }
- return 0;
-}
-
static jint openRBNFImpl1(JNIEnv* env, jclass clazz,
jint type, jstring locale) {
@@ -72,7 +46,7 @@
} else if(type == 3) {
style = URBNF_COUNT;
} else {
- icuError(env, U_ILLEGAL_ARGUMENT_ERROR);
+ icu4jni_error(env, U_ILLEGAL_ARGUMENT_ERROR);
}
Locale loc = Locale::createFromName(localeChars);
@@ -84,7 +58,7 @@
env->ReleaseStringUTFChars(locale, localeChars);
// check for an error
- if ( icuError(env, status) != FALSE) {
+ if (icu4jni_error(env, status) != FALSE) {
return 0;
}
@@ -117,7 +91,7 @@
env->ReleaseStringUTFChars(locale, localeChars);
// check for an error
- if ( icuError(env, status) != FALSE) {
+ if (icu4jni_error(env, status) != FALSE) {
return 0;
}
@@ -183,7 +157,7 @@
res.extract(result, reslenneeded + 1, status);
}
- if (icuError(env, status) != FALSE) {
+ if (icu4jni_error(env, status) != FALSE) {
free(result);
return NULL;
}
@@ -245,7 +219,7 @@
res.extract(result, reslenneeded + 1, status);
}
- if (icuError(env, status) != FALSE) {
+ if (icu4jni_error(env, status) != FALSE) {
free(result);
return NULL;
}
@@ -265,22 +239,11 @@
jobject position, jboolean lenient) {
// LOGI("ENTER parseRBNFImpl");
-
- const char * parsePositionClassName = "java/text/ParsePosition";
- const char * longClassName = "java/lang/Long";
- const char * doubleClassName = "java/lang/Double";
-
-
- UErrorCode status = U_ZERO_ERROR;
-
- UNumberFormat *fmt = (UNumberFormat *)(int)addr;
-
- jchar *str = (UChar *)env->GetStringChars(text, NULL);
- int strlength = env->GetStringLength(text);
-
- jclass parsePositionClass = env->FindClass(parsePositionClassName);
- jclass longClass = env->FindClass(longClassName);
- jclass doubleClass = env->FindClass(doubleClassName);
+
+ // TODO: cache these?
+ jclass parsePositionClass = env->FindClass("java/text/ParsePosition");
+ jclass longClass = env->FindClass("java/lang/Long");
+ jclass doubleClass = env->FindClass("java/lang/Double");
jmethodID getIndexMethodID = env->GetMethodID(parsePositionClass,
"getIndex", "()I");
@@ -292,22 +255,25 @@
jmethodID longInitMethodID = env->GetMethodID(longClass, "<init>", "(J)V");
jmethodID dblInitMethodID = env->GetMethodID(doubleClass, "<init>", "(D)V");
- int parsePos = env->CallIntMethod(position, getIndexMethodID, NULL);
-
// make sure the ParsePosition is valid. Actually icu4c would parse a number
// correctly even if the parsePosition is set to -1, but since the RI fails
// for that case we have to fail too
+ int parsePos = env->CallIntMethod(position, getIndexMethodID, NULL);
+ const int strlength = env->GetStringLength(text);
if(parsePos < 0 || parsePos > strlength) {
return NULL;
}
-
+
Formattable res;
-
+
+ jchar *str = (UChar *)env->GetStringChars(text, NULL);
+
const UnicodeString src((UChar*)str, strlength, strlength);
ParsePosition pp;
pp.setIndex(parsePos);
+ UNumberFormat *fmt = (UNumberFormat *)(int)addr;
if(lenient) {
unum_setAttribute(fmt, UNUM_LENIENT_PARSE, JNI_TRUE);
}
@@ -328,35 +294,23 @@
return NULL;
}
- Formattable::Type numType;
- numType = res.getType();
- UErrorCode fmtStatus;
-
- double resultDouble;
- long resultLong;
- int64_t resultInt64;
-
- switch(numType) {
- case Formattable::kDouble:
- resultDouble = res.getDouble();
- env->CallVoidMethod(position, setIndexMethodID, (jint) parsePos);
- return env->NewObject(doubleClass, dblInitMethodID,
- (jdouble) resultDouble);
- case Formattable::kLong:
- resultLong = res.getLong();
- env->CallVoidMethod(position, setIndexMethodID, (jint) parsePos);
- return env->NewObject(longClass, longInitMethodID,
- (jlong) resultLong);
- case Formattable::kInt64:
- resultInt64 = res.getInt64();
- env->CallVoidMethod(position, setIndexMethodID, (jint) parsePos);
- return env->NewObject(longClass, longInitMethodID,
- (jlong) resultInt64);
- default:
- break;
+ Formattable::Type numType = res.getType();
+ if (numType == Formattable::kDouble) {
+ double resultDouble = res.getDouble();
+ env->CallVoidMethod(position, setIndexMethodID, (jint) parsePos);
+ return env->NewObject(doubleClass, dblInitMethodID,
+ (jdouble) resultDouble);
+ } else if (numType == Formattable::kLong) {
+ long resultLong = res.getLong();
+ env->CallVoidMethod(position, setIndexMethodID, (jint) parsePos);
+ return env->NewObject(longClass, longInitMethodID, (jlong) resultLong);
+ } else if (numType == Formattable::kInt64) {
+ int64_t resultInt64 = res.getInt64();
+ env->CallVoidMethod(position, setIndexMethodID, (jint) parsePos);
+ return env->NewObject(longClass, longInitMethodID, (jlong) resultInt64);
+ } else {
+ return NULL;
}
-
- return NULL;
}
static JNINativeMethod gMethods[] = {
diff --git a/libcore/icu/src/main/native/RegExInterface.cpp b/libcore/icu/src/main/native/RegExInterface.cpp
index afa5cc4..0ca3d06 100644
--- a/libcore/icu/src/main/native/RegExInterface.cpp
+++ b/libcore/icu/src/main/native/RegExInterface.cpp
@@ -32,12 +32,12 @@
* character data it refers to (but does not have a copy of), so we can
* manage memory properly.
*/
-typedef struct RegExDataStruct {
+struct RegExData {
// A pointer to the ICU regular expression
URegularExpression* regex;
// A pointer to (a copy of) the input text that *we* manage
jchar* text;
-} RegExData;
+};
static void throwPatternSyntaxException(JNIEnv* env, UErrorCode status,
jstring pattern, UParseError error)
@@ -63,8 +63,8 @@
uregex_close(data->regex);
}
- if (data->text != NULL && data->text != &EMPTY_STRING) {
- free(data->text);
+ if (data->text != &EMPTY_STRING) {
+ delete[] data->text;
}
free(data);
@@ -125,8 +125,8 @@
return;
}
- if (data->text != NULL && data->text != &EMPTY_STRING) {
- free(data->text);
+ if (data->text != &EMPTY_STRING) {
+ delete[] data->text;
data->text = NULL;
}
@@ -134,11 +134,9 @@
if (textLen == 0) {
data->text = &EMPTY_STRING;
} else {
- jchar const * textRaw = env->GetStringChars(text, NULL);
- data->text = (jchar*)malloc((textLen + 1) * sizeof(jchar));
- memcpy(data->text, textRaw, textLen * sizeof(jchar));
+ data->text = new jchar[textLen + 1];
+ env->GetStringRegion(text, 0, textLen, data->text);
data->text[textLen] = 0;
- env->ReleaseStringChars(text, textRaw);
}
uregex_setText(data->regex, data->text, textLen, &status);
diff --git a/libcore/icu/src/main/native/ResourceInterface.cpp b/libcore/icu/src/main/native/ResourceInterface.cpp
index a88e15c..731cf3f 100644
--- a/libcore/icu/src/main/native/ResourceInterface.cpp
+++ b/libcore/icu/src/main/native/ResourceInterface.cpp
@@ -40,32 +40,6 @@
jclass string_class;
-static UBool icuError(JNIEnv *env, UErrorCode errorcode)
-{
- const char *emsg = u_errorName(errorcode);
- jclass exception;
-
- if (U_FAILURE(errorcode)) {
- switch (errorcode) {
- case U_ILLEGAL_ARGUMENT_ERROR :
- exception = env->FindClass("java/lang/IllegalArgumentException");
- break;
- case U_INDEX_OUTOFBOUNDS_ERROR :
- case U_BUFFER_OVERFLOW_ERROR :
- exception = env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
- break;
- case U_UNSUPPORTED_ERROR :
- exception = env->FindClass("java/lang/UnsupportedOperationException");
- break;
- default :
- exception = env->FindClass("java/lang/RuntimeException");
- }
-
- return (env->ThrowNew(exception, emsg) != 0);
- }
- return 0;
-}
-
static Locale getLocale(JNIEnv *env, jstring locale) {
const char *name = env->GetStringUTFChars(locale, NULL);
Locale result = Locale::createFromName(name);
diff --git a/libcore/icu/src/test/java/com/ibm/icu4jni/util/AllTests.java b/libcore/icu/src/test/java/com/ibm/icu4jni/util/AllTests.java
new file mode 100644
index 0000000..1b95075
--- /dev/null
+++ b/libcore/icu/src/test/java/com/ibm/icu4jni/util/AllTests.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+package com.ibm.icu4jni.util;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+ public static final Test suite() {
+ TestSuite suite = tests.TestSuiteFactory.createTestSuite();
+ suite.addTestSuite(com.ibm.icu4jni.util.ResourcesTest.class);
+ return suite;
+ }
+}
diff --git a/libcore/icu/src/test/java/com/ibm/icu4jni/util/ResourcesTest.java b/libcore/icu/src/test/java/com/ibm/icu4jni/util/ResourcesTest.java
new file mode 100644
index 0000000..4112d0b
--- /dev/null
+++ b/libcore/icu/src/test/java/com/ibm/icu4jni/util/ResourcesTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+package com.ibm.icu4jni.util;
+
+public class ResourcesTest extends junit.framework.TestCase {
+ public void test_getISOLanguages() throws Exception {
+ // Check that corrupting our array doesn't affect other callers.
+ assertNotNull(Resources.getISOLanguages()[0]);
+ Resources.getISOLanguages()[0] = null;
+ assertNotNull(Resources.getISOLanguages()[0]);
+ }
+
+ public void test_getISOCountries() throws Exception {
+ // Check that corrupting our array doesn't affect other callers.
+ assertNotNull(Resources.getISOCountries()[0]);
+ Resources.getISOCountries()[0] = null;
+ assertNotNull(Resources.getISOCountries()[0]);
+ }
+
+ public void test_getAvailableLocales() throws Exception {
+ // Check that corrupting our array doesn't affect other callers.
+ assertNotNull(Resources.getAvailableLocales()[0]);
+ Resources.getAvailableLocales()[0] = null;
+ assertNotNull(Resources.getAvailableLocales()[0]);
+ }
+
+ public void test_getKnownTimezones() throws Exception {
+ // Check that corrupting our array doesn't affect other callers.
+ assertNotNull(Resources.getKnownTimezones()[0]);
+ Resources.getKnownTimezones()[0] = null;
+ assertNotNull(Resources.getKnownTimezones()[0]);
+ }
+
+ public void test_getDisplayTimeZones() throws Exception {
+ // Check that corrupting our array doesn't affect other callers.
+ assertNotNull(Resources.getDisplayTimeZones(null)[0]);
+ Resources.getDisplayTimeZones(null)[0] = null;
+ assertNotNull(Resources.getDisplayTimeZones(null)[0]);
+ // getDisplayTimezones actually returns a String[][] rather than a String[].
+ assertNotNull(Resources.getDisplayTimeZones(null)[0][0]);
+ Resources.getDisplayTimeZones(null)[0][0] = null;
+ assertNotNull(Resources.getDisplayTimeZones(null)[0][0]);
+ }
+}
diff --git a/libcore/luni-kernel/src/main/java/java/lang/Package.java b/libcore/luni-kernel/src/main/java/java/lang/Package.java
index 2817404..4d98959 100644
--- a/libcore/luni-kernel/src/main/java/java/lang/Package.java
+++ b/libcore/luni-kernel/src/main/java/java/lang/Package.java
@@ -268,8 +268,8 @@
*/
public boolean isCompatibleWith(String version)
throws NumberFormatException {
- String[] requested = version.split(".");
- String[] provided = specVersion.split(".");
+ String[] requested = version.split("\\.");
+ String[] provided = specVersion.split("\\.");
for (int i = 0; i < Math.min(requested.length, provided.length); i++) {
int reqNum = Integer.parseInt(requested[i]);
@@ -318,4 +318,3 @@
return "package " + name;
}
}
-
diff --git a/libcore/luni-kernel/src/main/java/java/lang/ref/Reference.java b/libcore/luni-kernel/src/main/java/java/lang/ref/Reference.java
index ca7290b..c695830 100644
--- a/libcore/luni-kernel/src/main/java/java/lang/ref/Reference.java
+++ b/libcore/luni-kernel/src/main/java/java/lang/ref/Reference.java
@@ -49,7 +49,7 @@
* VM requirement: this field <em>must</em> be called "referent"
* and be an object.
*/
- T referent;
+ volatile T referent;
/**
* If non-null, the queue on which this reference will be enqueued
@@ -58,7 +58,7 @@
* and be a java.lang.ref.ReferenceQueue.
*/
@SuppressWarnings("unchecked")
- ReferenceQueue queue;
+ volatile ReferenceQueue queue;
/**
* Used internally by java.lang.ref.ReferenceQueue.
@@ -66,7 +66,7 @@
* and be a java.lang.ref.Reference.
*/
@SuppressWarnings("unchecked")
- Reference queueNext;
+ volatile Reference queueNext;
/**
* Used internally by Dalvik.
@@ -74,7 +74,7 @@
* and be an int.
*/
@SuppressWarnings("unused")
- private int vmData;
+ volatile private int vmData;
/**
* Constructs a new instance of this class.
diff --git a/libcore/luni-kernel/src/main/java/java/lang/reflect/Constructor.java b/libcore/luni-kernel/src/main/java/java/lang/reflect/Constructor.java
index c6927eb..3918d7e 100644
--- a/libcore/luni-kernel/src/main/java/java/lang/reflect/Constructor.java
+++ b/libcore/luni-kernel/src/main/java/java/lang/reflect/Constructor.java
@@ -161,12 +161,12 @@
appendArrayGenericType(sb,
Types.getClonedTypeArray(genericParameterTypes));
sb.append(')');
- // append exeptions if any
- Type[] genericEceptionTypeArray =
+ // append exceptions if any
+ Type[] genericExceptionTypeArray =
Types.getClonedTypeArray(genericExceptionTypes);
- if (genericEceptionTypeArray.length > 0) {
+ if (genericExceptionTypeArray.length > 0) {
sb.append(" throws ");
- appendArrayGenericType(sb, genericEceptionTypeArray);
+ appendArrayGenericType(sb, genericExceptionTypeArray);
}
return sb.toString();
}
@@ -314,7 +314,7 @@
public Class<?>[] getExceptionTypes() {
if (exceptionTypes == null)
return new Class[0];
- return exceptionTypes;
+ return exceptionTypes.clone();
}
/**
@@ -354,7 +354,7 @@
* @since Android 1.0
*/
public Class<?>[] getParameterTypes() {
- return parameterTypes;
+ return parameterTypes.clone();
}
/**
diff --git a/libcore/luni-kernel/src/main/java/java/lang/reflect/Method.java b/libcore/luni-kernel/src/main/java/java/lang/reflect/Method.java
index 473726d..dabf9a4 100644
--- a/libcore/luni-kernel/src/main/java/java/lang/reflect/Method.java
+++ b/libcore/luni-kernel/src/main/java/java/lang/reflect/Method.java
@@ -383,7 +383,7 @@
return new Class[0];
}
- return exceptionTypes;
+ return exceptionTypes.clone();
}
/**
@@ -424,7 +424,7 @@
* @since Android 1.0
*/
public Class<?>[] getParameterTypes() {
- return parameterTypes;
+ return parameterTypes.clone();
}
/**
@@ -521,7 +521,7 @@
return invokeNative (receiver, args, declaringClass, parameterTypes, returnType, slot, flag);
}
- private native Object invokeNative(Object obj, Object[] args, Class<?> declaringClass, Class<?>[] parameterTYpes, Class<?> returnType, int slot, boolean noAccessCheck)
+ private native Object invokeNative(Object obj, Object[] args, Class<?> declaringClass, Class<?>[] parameterTypes, Class<?> returnType, int slot, boolean noAccessCheck)
throws IllegalAccessException,
IllegalArgumentException,
InvocationTargetException;
diff --git a/libcore/luni-kernel/src/main/native/java_lang_ProcessManager.c b/libcore/luni-kernel/src/main/native/java_lang_ProcessManager.c
index eaefc9f..46e78f5 100644
--- a/libcore/luni-kernel/src/main/native/java_lang_ProcessManager.c
+++ b/libcore/luni-kernel/src/main/native/java_lang_ProcessManager.c
@@ -64,8 +64,7 @@
jclass clazz, jobject javaDescriptor) {
int fd = (*env)->GetIntField(env, javaDescriptor, descriptorField);
if (closeNow(fd) == -1) {
- jclass ioException = (*env)->FindClass(env, "java/io/IOException");
- (*env)->ThrowNew(env, ioException, strerror(errno));
+ jniThrowIOException(env, errno);
}
}
diff --git a/libcore/luni-kernel/src/test/java/java/lang/reflect/AllTests.java b/libcore/luni-kernel/src/test/java/java/lang/reflect/AllTests.java
new file mode 100644
index 0000000..7cf1475
--- /dev/null
+++ b/libcore/luni-kernel/src/test/java/java/lang/reflect/AllTests.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+package java.lang.reflect;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+ public static final Test suite() {
+ TestSuite suite = tests.TestSuiteFactory.createTestSuite();
+ suite.addTestSuite(java.lang.reflect.ConstructorTest.class);
+ suite.addTestSuite(java.lang.reflect.MethodTest.class);
+ return suite;
+ }
+}
diff --git a/libcore/luni-kernel/src/test/java/java/lang/reflect/ConstructorTest.java b/libcore/luni-kernel/src/test/java/java/lang/reflect/ConstructorTest.java
new file mode 100644
index 0000000..e2672a8
--- /dev/null
+++ b/libcore/luni-kernel/src/test/java/java/lang/reflect/ConstructorTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+package java.lang.reflect;
+
+public class ConstructorTest extends junit.framework.TestCase {
+ public void test_getExceptionTypes() throws Exception {
+ Constructor<?> constructor = ConstructorTestHelper.class.getConstructor(new Class[0]);
+ Class[] exceptions = constructor.getExceptionTypes();
+ assertEquals(1, exceptions.length);
+ assertEquals(IndexOutOfBoundsException.class, exceptions[0]);
+ // Check that corrupting our array doesn't affect other callers.
+ exceptions[0] = NullPointerException.class;
+ exceptions = constructor.getExceptionTypes();
+ assertEquals(1, exceptions.length);
+ assertEquals(IndexOutOfBoundsException.class, exceptions[0]);
+ }
+
+ public void test_getParameterTypes() throws Exception {
+ Class[] expectedParameters = new Class[] { Object.class };
+ Constructor<?> constructor = ConstructorTestHelper.class.getConstructor(expectedParameters);
+ Class[] parameters = constructor.getParameterTypes();
+ assertEquals(1, parameters.length);
+ assertEquals(expectedParameters[0], parameters[0]);
+ // Check that corrupting our array doesn't affect other callers.
+ parameters[0] = String.class;
+ parameters = constructor.getParameterTypes();
+ assertEquals(1, parameters.length);
+ assertEquals(expectedParameters[0], parameters[0]);
+ }
+
+ static class ConstructorTestHelper {
+ public ConstructorTestHelper() throws IndexOutOfBoundsException { }
+ public ConstructorTestHelper(Object o) { }
+ }
+}
diff --git a/libcore/luni-kernel/src/test/java/java/lang/reflect/MethodTest.java b/libcore/luni-kernel/src/test/java/java/lang/reflect/MethodTest.java
new file mode 100644
index 0000000..ed41de9
--- /dev/null
+++ b/libcore/luni-kernel/src/test/java/java/lang/reflect/MethodTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+package java.lang.reflect;
+
+public class MethodTest extends junit.framework.TestCase {
+ public void test_getExceptionTypes() throws Exception {
+ Method method = MethodTestHelper.class.getMethod("m1", new Class[0]);
+ Class[] exceptions = method.getExceptionTypes();
+ assertEquals(1, exceptions.length);
+ assertEquals(IndexOutOfBoundsException.class, exceptions[0]);
+ // Check that corrupting our array doesn't affect other callers.
+ exceptions[0] = NullPointerException.class;
+ exceptions = method.getExceptionTypes();
+ assertEquals(1, exceptions.length);
+ assertEquals(IndexOutOfBoundsException.class, exceptions[0]);
+ }
+
+ public void test_getParameterTypes() throws Exception {
+ Class[] expectedParameters = new Class[] { Object.class };
+ Method method = MethodTestHelper.class.getMethod("m2", expectedParameters);
+ Class[] parameters = method.getParameterTypes();
+ assertEquals(1, parameters.length);
+ assertEquals(expectedParameters[0], parameters[0]);
+ // Check that corrupting our array doesn't affect other callers.
+ parameters[0] = String.class;
+ parameters = method.getParameterTypes();
+ assertEquals(1, parameters.length);
+ assertEquals(expectedParameters[0], parameters[0]);
+ }
+
+ static class MethodTestHelper {
+ public void m1() throws IndexOutOfBoundsException { }
+ public void m2(Object o) { }
+ }
+}
diff --git a/libcore/luni-kernel/src/test/java/tests/api/org/apache/harmony/kernel/dalvik/AllTests.java b/libcore/luni-kernel/src/test/java/tests/api/org/apache/harmony/kernel/dalvik/AllTests.java
new file mode 100644
index 0000000..a59cc3e
--- /dev/null
+++ b/libcore/luni-kernel/src/test/java/tests/api/org/apache/harmony/kernel/dalvik/AllTests.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+package tests.api.org.apache.harmony.kernel.dalvik;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+ public static final Test suite() {
+ TestSuite suite = tests.TestSuiteFactory.createTestSuite();
+ suite.addTestSuite(tests.api.org.apache.harmony.kernel.dalvik.ThreadsTest.class);
+ return suite;
+ }
+}
diff --git a/libcore/luni/src/main/java/java/io/BufferedOutputStream.java b/libcore/luni/src/main/java/java/io/BufferedOutputStream.java
index 6d52dee..8b7c4f5 100644
--- a/libcore/luni/src/main/java/java/io/BufferedOutputStream.java
+++ b/libcore/luni/src/main/java/java/io/BufferedOutputStream.java
@@ -148,17 +148,16 @@
out.write(buffer, offset, length);
return;
}
-
- // BEGIN android-changed
- // Exception priorities (in case of multiple errors) differ from
- // RI, but are spec-compliant.
- // used (offset | length) < 0 instead of (offset < 0) || (length < 0)
- // to safe one operation
- if ((offset | length) < 0 || offset > buffer.length - length) {
- // K002f=Arguments out of bounds
- throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
+
+ if (offset < 0 || offset > buffer.length - length) {
+ // K002e=Offset out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
+
}
- // END android-changed
+ if (length < 0) {
+ // K0031=Length out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
+ }
// flush the internal buffer first if we have not enough space left
if (length >= (buf.length - count)) {
diff --git a/libcore/luni/src/main/java/java/io/CharArrayReader.java b/libcore/luni/src/main/java/java/io/CharArrayReader.java
index d2757f6..6753faa 100644
--- a/libcore/luni/src/main/java/java/io/CharArrayReader.java
+++ b/libcore/luni/src/main/java/java/io/CharArrayReader.java
@@ -213,20 +213,16 @@
// BEGIN android-note
// changed array notation to be consistent with the rest of harmony
// END android-note
- // avoid int overflow
- // BEGIN android-changed
- // Exception priorities (in case of multiple errors) differ from
- // RI, but are spec-compliant.
- // made implicit null check explicit,
- // removed redundant check, used (offset | len) < 0 instead of
- // (offset < 0) || (len < 0) to safe one operation
- if (buffer == null) {
- throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
+ if (offset < 0 || offset > buffer.length) {
+ // K002e=Offset out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(
+ Msg.getString("K002e", offset)); //$NON-NLS-1$
}
- if ((offset | len) < 0 || len > buffer.length - offset) {
- throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
+ if (len < 0 || len > buffer.length - offset) {
+ // K0031=Length out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(
+ Msg.getString("K0031", len)); //$NON-NLS-1$
}
- // END android-changed
synchronized (lock) {
if (isClosed()) {
throw new IOException(Msg.getString("K0060")); //$NON-NLS-1$
diff --git a/libcore/luni/src/main/java/java/io/DataOutputStream.java b/libcore/luni/src/main/java/java/io/DataOutputStream.java
index 18e04a5..4152173 100644
--- a/libcore/luni/src/main/java/java/io/DataOutputStream.java
+++ b/libcore/luni/src/main/java/java/io/DataOutputStream.java
@@ -280,6 +280,19 @@
written += 8;
}
+ int writeLongToBuffer(long val,
+ byte[] buffer, int offset) throws IOException {
+ buffer[offset++] = (byte) (val >> 56);
+ buffer[offset++] = (byte) (val >> 48);
+ buffer[offset++] = (byte) (val >> 40);
+ buffer[offset++] = (byte) (val >> 32);
+ buffer[offset++] = (byte) (val >> 24);
+ buffer[offset++] = (byte) (val >> 16);
+ buffer[offset++] = (byte) (val >> 8);
+ buffer[offset++] = (byte) val;
+ return offset;
+ }
+
/**
* Writes the specified 16-bit short to the target stream. Only the lower
* two bytes of the integer {@code val} are written, with the higher one
@@ -299,6 +312,13 @@
written += 2;
}
+ int writeShortToBuffer(int val,
+ byte[] buffer, int offset) throws IOException {
+ buffer[offset++] = (byte) (val >> 8);
+ buffer[offset++] = (byte) val;
+ return offset;
+ }
+
/**
* Writes the specified encoded in {@link DataInput modified UTF-8} to this
* stream.
@@ -317,8 +337,14 @@
if (utfCount > 65535) {
throw new UTFDataFormatException(Msg.getString("K0068")); //$NON-NLS-1$
}
- writeShort((int) utfCount);
- writeUTFBytes(str, utfCount);
+ byte[] buffer = new byte[(int)utfCount + 2];
+ int offset = 0;
+ offset = writeShortToBuffer((int) utfCount, buffer, offset);
+ // BEGIN android-changed
+ // removed unused parameter count
+ offset = writeUTFBytesToBuffer(str, buffer, offset);
+ // BEGIN android-changed
+ write(buffer, 0, offset);
}
long countUTFBytes(String str) {
@@ -336,24 +362,25 @@
return utfCount;
}
- void writeUTFBytes(String str, long count) throws IOException {
- int size = (int) count;
+ int writeUTFBytesToBuffer(String str,
+ byte[] buffer, int offset) throws IOException {
+ // BEGIN android-note
+ // removed unused parameter count
+ // END android-note
int length = str.length();
- byte[] utfBytes = new byte[size];
- int utfIndex = 0;
for (int i = 0; i < length; i++) {
int charValue = str.charAt(i);
if (charValue > 0 && charValue <= 127) {
- utfBytes[utfIndex++] = (byte) charValue;
+ buffer[offset++] = (byte) charValue;
} else if (charValue <= 2047) {
- utfBytes[utfIndex++] = (byte) (0xc0 | (0x1f & (charValue >> 6)));
- utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue));
+ buffer[offset++] = (byte) (0xc0 | (0x1f & (charValue >> 6)));
+ buffer[offset++] = (byte) (0x80 | (0x3f & charValue));
} else {
- utfBytes[utfIndex++] = (byte) (0xe0 | (0x0f & (charValue >> 12)));
- utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & (charValue >> 6)));
- utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue));
+ buffer[offset++] = (byte) (0xe0 | (0x0f & (charValue >> 12)));
+ buffer[offset++] = (byte) (0x80 | (0x3f & (charValue >> 6)));
+ buffer[offset++] = (byte) (0x80 | (0x3f & charValue));
}
}
- write(utfBytes, 0, utfIndex);
+ return offset;
}
}
diff --git a/libcore/luni/src/main/java/java/io/EmulatedFieldsForDumping.java b/libcore/luni/src/main/java/java/io/EmulatedFieldsForDumping.java
index 16c7986..c3743dd 100644
--- a/libcore/luni/src/main/java/java/io/EmulatedFieldsForDumping.java
+++ b/libcore/luni/src/main/java/java/io/EmulatedFieldsForDumping.java
@@ -192,7 +192,6 @@
*/
@Override
@Deprecated
- @SuppressWarnings("deprecation")
public void write(ObjectOutput output) throws IOException {
EmulatedFields.ObjectSlot[] slots = emulatedFields.slots();
for (int i = 0; i < slots.length; i++) {
diff --git a/libcore/luni/src/main/java/java/io/File.java b/libcore/luni/src/main/java/java/io/File.java
index c802995..cde9fcc 100644
--- a/libcore/luni/src/main/java/java/io/File.java
+++ b/libcore/luni/src/main/java/java/io/File.java
@@ -761,9 +761,8 @@
* Indicates if this file's pathname is absolute. Whether a pathname is
* absolute is platform specific. On UNIX, absolute paths must start with
* the character '/'; on Windows it is absolute if either it starts with
- * '\', '/', '\\' (to represent a file server), or a letter followed by a
- * colon.
- *
+ * '\\' (to represent a file server), or a letter followed by a colon.
+ *
* @return {@code true} if this file's pathname is absolute, {@code false}
* otherwise.
* @see #getPath
@@ -775,10 +774,6 @@
// END android-changed
}
- // BEGIN android-removed
- // private native boolean isAbsoluteImpl(byte[] filePath);
- // END android-removed
-
/**
* Indicates if this file represents a <em>directory</em> on the
* underlying file system.
@@ -1358,8 +1353,10 @@
if (properPath != null) {
return properPath;
}
- if(path.length() > 0 && path.charAt(0) == separatorChar) {
- return properPath = Util.getBytes(path);
+
+ if (isAbsolute()) {
+ byte[] pathBytes = Util.getUTF8Bytes(path);
+ return properPath = pathBytes;
}
// Check security by getting user.dir when the path is not absolute
String userdir;
@@ -1380,10 +1377,6 @@
}
// END android-changed
- // BEGIN android-removed
- // private static native byte[] properPathImpl(byte[] path);
- // END android-removed
-
/**
* Renames this file to the name represented by the {@code dest} file. This
* works for both normal files and directories.
diff --git a/libcore/luni/src/main/java/java/io/FileInputStream.java b/libcore/luni/src/main/java/java/io/FileInputStream.java
index 1243262..077cd23 100644
--- a/libcore/luni/src/main/java/java/io/FileInputStream.java
+++ b/libcore/luni/src/main/java/java/io/FileInputStream.java
@@ -69,9 +69,14 @@
super();
SecurityManager security = System.getSecurityManager();
if (security != null) {
+ // For compatibility, nulls are passed to the manager.
String filePath = (null == file ? null : file.getPath());
security.checkRead(filePath);
}
+ if (file == null) {
+ // KA001=Argument must not be null
+ throw new NullPointerException(Msg.getString("KA001")); //$NON-NLS-1$
+ }
fd = new FileDescriptor();
fd.readOnly = true;
fd.descriptor = fileSystem.open(file.properPath(true),
@@ -312,25 +317,24 @@
}
openCheck();
synchronized (repositioningLock) {
- // stdin requires special handling
- if (fd == FileDescriptor.in) {
- return (int) fileSystem.ttyRead(buffer, offset, count);
- }
+ // BEGIN android-changed
+ // If you only support Linux, there's nothing special about stdin.
return (int) fileSystem.read(fd.descriptor, buffer, offset, count);
+ // END android-changed
}
}
/**
* Skips {@code count} number of bytes in this stream. Subsequent
- * {@code read()}'s will not return these bytes unless {@code reset()} is
- * used. This method may perform multiple reads to read {@code count} bytes.
+ * {@code read()}s will not return these bytes unless {@code reset()} is
+ * used. If the underlying stream is unseekable, an IOException is thrown.
*
* @param count
* the number of bytes to skip.
* @return the number of bytes actually skipped.
* @throws IOException
- * if {@code count < 0}, this stream is closed or another
- * IOException occurs.
+ * if {@code count < 0}, this stream is closed or unseekable,
+ * or another IOException occurs.
*/
@Override
public long skip(long count) throws IOException {
@@ -344,29 +348,18 @@
throw new IOException(Msg.getString("KA013")); //$NON-NLS-1$
}
- // stdin requires special handling
- if (fd == FileDescriptor.in) {
- // Read and discard count bytes in 8k chunks
- long skipped = 0, numRead;
- int chunk = count < 8192 ? (int) count : 8192;
- byte[] buffer = new byte[chunk];
- for (long i = count / chunk; i >= 0; i--) {
- numRead = fileSystem.ttyRead(buffer, 0, chunk);
- skipped += numRead;
- if (numRead < chunk) {
- return skipped;
- }
- }
- return skipped;
- }
-
+ // BEGIN android-changed
+ // The RI doesn't treat stdin as special. It throws IOException for
+ // all non-seekable streams, so we do too. If you did want to support
+ // non-seekable streams, the best way to do it would be to recognize
+ // when lseek(2) fails with ESPIPE and call super.skip(count).
synchronized (repositioningLock) {
- final long currentPosition = fileSystem.seek(fd.descriptor, 0L,
- IFileSystem.SEEK_CUR);
- final long newPosition = fileSystem.seek(fd.descriptor,
- currentPosition + count, IFileSystem.SEEK_SET);
- return newPosition - currentPosition;
+ // Our seek returns the new offset, but we know it will throw an
+ // exception if it couldn't perform exactly the seek we asked for.
+ fileSystem.seek(fd.descriptor, count, IFileSystem.SEEK_CUR);
+ return count;
}
+ // END android-changed
}
private synchronized void openCheck() throws IOException {
diff --git a/libcore/luni/src/main/java/java/io/FilterOutputStream.java b/libcore/luni/src/main/java/java/io/FilterOutputStream.java
index 66765f9..fa837ee 100644
--- a/libcore/luni/src/main/java/java/io/FilterOutputStream.java
+++ b/libcore/luni/src/main/java/java/io/FilterOutputStream.java
@@ -102,7 +102,7 @@
* the buffer to write.
* @param offset
* the index of the first byte in {@code buffer} to write.
- * @param count
+ * @param length
* the number of bytes in {@code buffer} to write.
* @throws IndexOutOfBoundsException
* if {@code offset < 0} or {@code count < 0}, or if
@@ -112,25 +112,20 @@
* if an I/O error occurs while writing to this stream.
*/
@Override
- public void write(byte[] buffer, int offset, int count) throws IOException {
+ public void write(byte[] buffer, int offset, int length) throws IOException {
// BEGIN android-note
// changed array notation to be consistent with the rest of harmony
// END android-note
- // avoid int overflow, force null buffer check first
- // BEGIN android-changed
- // Exception priorities (in case of multiple errors) differ from
- // RI, but are spec-compliant.
- // removed redundant check, made implicit null check explicit,
- // used (offset | count) < 0 instead of (offset < 0) || (count < 0)
- // to safe one operation
- if (buffer == null) {
- throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
+ // Force null buffer check first!
+ if (offset > buffer.length || offset < 0) {
+ // K002e=Offset out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
}
- if ((offset | count) < 0 || count > buffer.length - offset) {
- throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
+ if (length < 0 || length > buffer.length - offset) {
+ // K0031=Length out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
}
- // END android-changed
- for (int i = 0; i < count; i++) {
+ for (int i = 0; i < length; i++) {
// Call write() instead of out.write() since subclasses could
// override the write() method.
write(buffer[offset + i]);
diff --git a/libcore/luni/src/main/java/java/io/InputStream.java b/libcore/luni/src/main/java/java/io/InputStream.java
index f20ce7d..33a5cfd 100644
--- a/libcore/luni/src/main/java/java/io/InputStream.java
+++ b/libcore/luni/src/main/java/java/io/InputStream.java
@@ -17,9 +17,7 @@
package java.io;
-// BEGIN android-added
import org.apache.harmony.luni.util.Msg;
-// END android-added
/**
* The base class for all input streams. An input stream is a means of reading
@@ -157,20 +155,15 @@
// BEGIN android-note
// changed array notation to be consistent with the rest of harmony
// END android-note
- // avoid int overflow, check null b
- // BEGIN android-changed
- // Exception priorities (in case of multiple errors) differ from
- // RI, but are spec-compliant.
- // removed redundant check, made implicit null check explicit,
- // used (offset | length) < 0 instead of (offset < 0) || (length < 0)
- // to safe one operation
- if (b == null) {
- throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
+ // Force null check for b first!
+ if (offset > b.length || offset < 0) {
+ // K002e=Offset out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
+ }
+ if (length < 0 || length > b.length - offset) {
+ // K0031=Length out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
}
- if ((offset | length) < 0 || length > b.length - offset) {
- throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
- }
- // END android-changed
for (int i = 0; i < length; i++) {
int c;
try {
@@ -224,11 +217,16 @@
}
long skipped = 0;
int toRead = n < 4096 ? (int) n : 4096;
- if (skipBuf == null || skipBuf.length < toRead) {
- skipBuf = new byte[toRead];
+ // We are unsynchronized, so take a local copy of the skipBuf at some
+ // point in time.
+ byte[] localBuf = skipBuf;
+ if (localBuf == null || localBuf.length < toRead) {
+ // May be lazily written back to the static. No matter if it
+ // overwrites somebody else's store.
+ skipBuf = localBuf = new byte[toRead];
}
while (skipped < n) {
- int read = read(skipBuf, 0, toRead);
+ int read = read(localBuf, 0, toRead);
if (read == -1) {
return skipped;
}
diff --git a/libcore/luni/src/main/java/java/io/LineNumberInputStream.java b/libcore/luni/src/main/java/java/io/LineNumberInputStream.java
index 1a40177..3df3a05 100644
--- a/libcore/luni/src/main/java/java/io/LineNumberInputStream.java
+++ b/libcore/luni/src/main/java/java/io/LineNumberInputStream.java
@@ -17,9 +17,7 @@
package java.io;
-// BEGIN android-added
import org.apache.harmony.luni.util.Msg;
-// END android-added
/**
* Wraps an existing {@link InputStream} and counts the line terminators
@@ -171,19 +169,15 @@
*/
@Override
public int read(byte[] buffer, int offset, int length) throws IOException {
- // BEGIN android-changed
- if (buffer == null) {
- throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
+ // Force buffer null check first!
+ if (offset > buffer.length || offset < 0) {
+ // K002e=Offset out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
+ }
+ if (length < 0 || length > buffer.length - offset) {
+ // K0031=Length out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
}
- // avoid int overflow
- // Exception priorities (in case of multiple errors) differ from
- // RI, but are spec-compliant.
- // removed redundant check, used (offset | length) < 0
- // instead of (offset < 0) || (length < 0) to safe one operation
- if ((offset | length) < 0 || length > buffer.length - offset) {
- throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
- }
- // END android-changed
for (int i = 0; i < length; i++) {
int currentChar;
diff --git a/libcore/luni/src/main/java/java/io/NotSerializableException.java b/libcore/luni/src/main/java/java/io/NotSerializableException.java
index f6e93a7..d85586a 100644
--- a/libcore/luni/src/main/java/java/io/NotSerializableException.java
+++ b/libcore/luni/src/main/java/java/io/NotSerializableException.java
@@ -19,9 +19,9 @@
/**
* Signals that an object that is not serializable has been passed into the
- * {@code ObjectOutput.writeObject()} mthod. This can happen if the object does
- * not implement {@code Serializable} or {@code Externalizable}, or if it is
- * serializable but it overrides {@code writeObject(ObjectOutputStream)} and
+ * {@code ObjectOutput.writeObject()} method. This can happen if the object
+ * does not implement {@code Serializable} or {@code Externalizable}, or if it
+ * is serializable but it overrides {@code writeObject(ObjectOutputStream)} and
* explicitly prevents serialization by throwing this type of exception.
*
* @see ObjectOutput#writeObject(Object)
diff --git a/libcore/luni/src/main/java/java/io/ObjectInputStream.java b/libcore/luni/src/main/java/java/io/ObjectInputStream.java
index 6d24eb2..df6d9a2 100644
--- a/libcore/luni/src/main/java/java/io/ObjectInputStream.java
+++ b/libcore/luni/src/main/java/java/io/ObjectInputStream.java
@@ -701,19 +701,15 @@
*/
@Override
public int read(byte[] buffer, int offset, int length) throws IOException {
- // BEGIN android-changed
- if (buffer == null) {
- throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
+ // Force buffer null check first!
+ if (offset > buffer.length || offset < 0) {
+ // K002e=Offset out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
}
- // avoid int overflow
- // Exception priorities (in case of multiple errors) differ from
- // RI, but are spec-compliant.
- // removed redundant check, used (offset | length) < 0 instead of
- // (offset < 0) || (length < 0) to safe one operation
- if ((offset | length) < 0 || length > buffer.length - offset) {
- throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
+ if (length < 0 || length > buffer.length - offset) {
+ // K0031=Length out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
}
- // END android-changed
if (length == 0) {
return 0;
}
diff --git a/libcore/luni/src/main/java/java/io/ObjectOutputStream.java b/libcore/luni/src/main/java/java/io/ObjectOutputStream.java
index e3c1471..7c85d4b 100644
--- a/libcore/luni/src/main/java/java/io/ObjectOutputStream.java
+++ b/libcore/luni/src/main/java/java/io/ObjectOutputStream.java
@@ -1617,14 +1617,19 @@
private Integer writeNewString(String object, boolean unshared)
throws IOException {
long count = output.countUTFBytes(object);
+ byte[] buffer;
+ int offset = 0;
if (count <= 0xffff) {
- output.writeByte(TC_STRING);
- output.writeShort((short) count);
+ buffer = new byte[(int)count+3];
+ buffer[offset++] = TC_STRING;
+ offset = output.writeShortToBuffer((short) count, buffer, offset);
} else {
- output.writeByte(TC_LONGSTRING);
- output.writeLong(count);
+ buffer = new byte[(int)count+9];
+ buffer[offset++] = TC_LONGSTRING;
+ offset = output.writeLongToBuffer(count, buffer, offset);
}
- output.writeUTFBytes(object, count);
+ offset = output.writeUTFBytesToBuffer(object, buffer, offset);
+ output.write(buffer, 0, offset);
Integer handle = nextHandle();
diff --git a/libcore/luni/src/main/java/java/io/PrintStream.java b/libcore/luni/src/main/java/java/io/PrintStream.java
index 29d460e..8b6464b 100644
--- a/libcore/luni/src/main/java/java/io/PrintStream.java
+++ b/libcore/luni/src/main/java/java/io/PrintStream.java
@@ -658,7 +658,7 @@
* the buffer to be written.
* @param offset
* the index of the first byte in {@code buffer} to write.
- * @param count
+ * @param length
* the number of bytes in {@code buffer} to write.
* @throws IndexOutOfBoundsException
* if {@code offset < 0} or {@code count < 0}, or if {@code
@@ -666,27 +666,23 @@
* @see #flush()
*/
@Override
- public void write(byte[] buffer, int offset, int count) {
- // BEGIN android-changed
- if (buffer == null) {
- throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
+ public void write(byte[] buffer, int offset, int length) {
+ // Force buffer null check first!
+ if (offset > buffer.length || offset < 0) {
+ // K002e=Offset out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
}
- // avoid int overflow
- // Exception priorities (in case of multiple errors) differ from
- // RI, but are spec-compliant.
- // removed redundant check, used (offset | count) < 0
- // instead of (offset < 0) || (count < 0) to safe one operation
- if ((offset | count) < 0 || count > buffer.length - offset) {
- throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
+ if (length < 0 || length > buffer.length - offset) {
+ // K0031=Length out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
}
- // END android-changed
synchronized (this) {
if (out == null) {
setError();
return;
}
try {
- out.write(buffer, offset, count);
+ out.write(buffer, offset, length);
if (autoflush) {
flush();
}
diff --git a/libcore/luni/src/main/java/java/io/PushbackInputStream.java b/libcore/luni/src/main/java/java/io/PushbackInputStream.java
index 4600fa2..932a896 100644
--- a/libcore/luni/src/main/java/java/io/PushbackInputStream.java
+++ b/libcore/luni/src/main/java/java/io/PushbackInputStream.java
@@ -177,21 +177,18 @@
@Override
public int read(byte[] buffer, int offset, int length) throws IOException {
if (buf == null) {
- throw new IOException();
+ // K0059=Stream is closed
+ throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
}
- // BEGIN android-changed
- if (buffer == null) {
- throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
+ // Force buffer null check first!
+ if (offset > buffer.length || offset < 0) {
+ // K002e=Offset out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
}
- // avoid int overflow
- // Exception priorities (in case of multiple errors) differ from
- // RI, but are spec-compliant.
- // removed redundant check, used (offset | length) < 0
- // instead of (offset < 0) || (length < 0) to safe one operation
- if ((offset | length) < 0 || length > buffer.length - offset) {
- throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
+ if (length < 0 || length > buffer.length - offset) {
+ // K0031=Length out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
}
- // END android-changed
int copiedBytes = 0, copyLength = 0, newOffset = offset;
// Are there pushback bytes available?
@@ -296,27 +293,22 @@
public void unread(byte[] buffer, int offset, int length)
throws IOException {
if (length > pos) {
- // Pushback buffer full
+ // K007e=Pushback buffer full
throw new IOException(Msg.getString("K007e")); //$NON-NLS-1$
}
- // avoid int overflow
- // BEGIN android-changed
- // Exception priorities (in case of multiple errors) differ from
- // RI, but are spec-compliant.
- // removed redundant check, made implicit null check explicit
- // used (offset | length) < 0 instead of (offset < 0) || (length < 0)
- // to safe one operation
- if (buffer == null) {
- throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
+ if (offset > buffer.length || offset < 0) {
+ // K002e=Offset out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
}
- if ((offset | length) < 0 || length > buffer.length - offset) {
- throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
+ if (length < 0 || length > buffer.length - offset) {
+ // K0031=Length out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
}
- // END android-changed
-
if (buf == null) {
- throw new IOException();
+ // K0059=Stream is closed
+ throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
}
+
System.arraycopy(buffer, offset, buf, pos - length, length);
pos = pos - length;
}
diff --git a/libcore/luni/src/main/java/java/io/PushbackReader.java b/libcore/luni/src/main/java/java/io/PushbackReader.java
index 606ecb4..016cd2f 100644
--- a/libcore/luni/src/main/java/java/io/PushbackReader.java
+++ b/libcore/luni/src/main/java/java/io/PushbackReader.java
@@ -298,7 +298,7 @@
* reader.
* @param offset
* the index of the first byte in {@code buffer} to push back.
- * @param count
+ * @param length
* the number of bytes to push back.
* @throws IndexOutOfBoundsException
* if {@code offset < 0} or {@code count < 0}, or if
@@ -311,29 +311,27 @@
* @throws NullPointerException
* if {@code buffer} is {@code null}.
*/
- public void unread(char[] buffer, int offset, int count) throws IOException {
+ public void unread(char[] buffer, int offset, int length) throws IOException {
synchronized (lock) {
if (buf == null) {
+ // K0059=Stream is closed
throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
}
- if (count > pos) {
- // Pushback buffer full
+ if (length > pos) {
+ // K007e=Pushback buffer full
throw new IOException(Msg.getString("K007e")); //$NON-NLS-1$
}
- // BEGIN android-changed
- if (buffer == null) {
- throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
+ // Force buffer null check first!
+ if (offset > buffer.length - length || offset < 0) {
+ // K002e=Offset out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
}
- // avoid int overflow
- // Exception priorities (in case of multiple errors) differ from
- // RI, but are spec-compliant.
- // used (offset | count) < 0 instead of (offset < 0) || (count < 0)
- // to safe one operation
- if ((offset | count) < 0 || offset > buffer.length - count) {
- throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
+ if (length < 0) {
+ // K0031=Length out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
}
- // END android-changed
- for (int i = offset + count - 1; i >= offset; i--) {
+
+ for (int i = offset + length - 1; i >= offset; i--) {
unread(buffer[i]);
}
}
diff --git a/libcore/luni/src/main/java/java/io/StringBufferInputStream.java b/libcore/luni/src/main/java/java/io/StringBufferInputStream.java
index cc4ab81..037cc60 100644
--- a/libcore/luni/src/main/java/java/io/StringBufferInputStream.java
+++ b/libcore/luni/src/main/java/java/io/StringBufferInputStream.java
@@ -115,18 +115,19 @@
return -1;
}
if (b == null) {
+ // K0047=buffer is null
throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
}
// avoid int overflow
- // BEGIN android-changed
- // Exception priorities (in case of multiple errors) differ from
- // RI, but are spec-compliant.
- // removed redundant check, used (offset | length) < 0
- // instead of (offset < 0) || (length < 0) to safe one operation
- if ((offset | length) < 0 || length > b.length - offset) {
- throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
+ if (offset < 0 || offset > b.length) {
+ // K002e=Offset out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
}
- // END android-changed
+ if (length < 0 || length > b.length - offset) {
+ // K0031=Length out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
+ }
+
if (length == 0) {
return 0;
}
diff --git a/libcore/luni/src/main/java/java/io/StringReader.java b/libcore/luni/src/main/java/java/io/StringReader.java
index 0a9e9bb..9f8671a 100644
--- a/libcore/luni/src/main/java/java/io/StringReader.java
+++ b/libcore/luni/src/main/java/java/io/StringReader.java
@@ -155,23 +155,19 @@
// BEGIN android-note
// changed array notation to be consistent with the rest of harmony
// END android-note
- // BEGIN android-changed
- // Exception priorities (in case of multiple errors) differ from
- // RI, but are spec-compliant.
- // removed redundant check, added null check, used (offset | len) < 0
- // instead of (offset < 0) || (len < 0) to safe one operation
- if (buf == null) {
- throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
- }
synchronized (lock) {
- // avoid int overflow
- if ((offset | len) < 0 || len > buf.length - offset) {
- throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
- }
- // END android-changed
if (isClosed()) {
+ // K0083=StringReader is closed.
throw new IOException(Msg.getString("K0083")); //$NON-NLS-1$
}
+ if (offset < 0 || offset > buf.length) {
+ // K002e=Offset out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
+ }
+ if (len < 0 || len > buf.length - offset) {
+ // K0031=Length out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", len)); //$NON-NLS-1$
+ }
if (len == 0) {
return 0;
}
diff --git a/libcore/luni/src/main/java/java/lang/AbstractStringBuilder.java b/libcore/luni/src/main/java/java/lang/AbstractStringBuilder.java
index c481e11..869c694 100644
--- a/libcore/luni/src/main/java/java/lang/AbstractStringBuilder.java
+++ b/libcore/luni/src/main/java/java/lang/AbstractStringBuilder.java
@@ -120,21 +120,23 @@
count = newSize;
}
- final void append0(char chars[], int start, int length) {
- if (chars == null) {
- throw new NullPointerException();
+ final void append0(char[] chars, int offset, int length) {
+ // Force null check of chars first!
+ if (offset > chars.length || offset < 0) {
+ // K002e=Offset out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
}
- // start + length could overflow, start/length maybe MaxInt
- if (start >= 0 && 0 <= length && length <= chars.length - start) {
- int newSize = count + length;
- if (newSize > value.length) {
- enlargeBuffer(newSize);
- }
- System.arraycopy(chars, start, value, count, length);
- count = newSize;
- } else {
- throw new ArrayIndexOutOfBoundsException();
+ if (length < 0 || chars.length - offset < length) {
+ // K0031=Length out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
}
+
+ int newSize = count + length;
+ if (newSize > value.length) {
+ enlargeBuffer(newSize);
+ }
+ System.arraycopy(chars, offset, value, count, length);
+ count = newSize;
}
final void append0(char ch) {
diff --git a/libcore/luni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java b/libcore/luni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java
index d43a7e6..6bb67fc 100644
--- a/libcore/luni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java
+++ b/libcore/luni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java
@@ -44,6 +44,7 @@
* the invalid index.
*/
public ArrayIndexOutOfBoundsException(int index) {
+ // K0052=Array index out of range\: {0}
super(Msg.getString("K0052", index)); //$NON-NLS-1$
}
diff --git a/libcore/luni/src/main/java/java/lang/Enum.java b/libcore/luni/src/main/java/java/lang/Enum.java
index 395c825..e2ee32a 100644
--- a/libcore/luni/src/main/java/java/lang/Enum.java
+++ b/libcore/luni/src/main/java/java/lang/Enum.java
@@ -25,7 +25,7 @@
/**
* The superclass of all enumerated types. Actual enumeration types inherit from
- * this class, but extending this class does not make a class an enumration
+ * this class, but extending this class does not make a class an enumeration
* type, since the compiler needs to generate special information for it.
*/
public abstract class Enum<E extends Enum<E>> implements Serializable,
diff --git a/libcore/luni/src/main/java/java/lang/Integer.java b/libcore/luni/src/main/java/java/lang/Integer.java
index 570120b..5dcf217 100644
--- a/libcore/luni/src/main/java/java/lang/Integer.java
+++ b/libcore/luni/src/main/java/java/lang/Integer.java
@@ -526,7 +526,7 @@
int quot = positive_value;
do {
int res = quot / 10;
- int digit_value = quot - (res * 10);
+ int digit_value = quot - ((res << 3) + (res << 1));
digit_value += '0';
buffer[last_digit++] = (char) digit_value;
quot = res;
diff --git a/libcore/luni/src/main/java/java/lang/Math.java b/libcore/luni/src/main/java/java/lang/Math.java
index d06e6e4..f7b49b2 100644
--- a/libcore/luni/src/main/java/java/lang/Math.java
+++ b/libcore/luni/src/main/java/java/lang/Math.java
@@ -246,9 +246,7 @@
* the value whose closest integer value has to be computed.
* @return the ceiling of the argument.
*/
- // BEGIN android-changed
public static native double ceil(double d);
- // END android-changed
/**
* Returns the closest double approximation of the cosine of the argument.
@@ -348,9 +346,7 @@
* the value whose closest integer value has to be computed.
* @return the floor of the argument.
*/
- // BEGIN android-changed
public static native double floor(double d);
- // END android-changed
/**
* Returns {@code sqrt(}<i>{@code x}</i><sup>{@code 2}</sup>{@code +} <i>
@@ -731,9 +727,7 @@
* the value to be rounded.
* @return the closest integer to the argument (as a double).
*/
- // BEGIN android-changed
public static native double rint(double d);
- // END android-changed
/**
* Returns the result of rounding the argument to an integer. The result is
diff --git a/libcore/luni/src/main/java/java/lang/SecurityManager.java b/libcore/luni/src/main/java/java/lang/SecurityManager.java
index 9125850..8a04e92 100644
--- a/libcore/luni/src/main/java/java/lang/SecurityManager.java
+++ b/libcore/luni/src/main/java/java/lang/SecurityManager.java
@@ -414,9 +414,8 @@
.getSecurityProperty(property));
if (list != null) {
int plen = pkg.length();
- StringTokenizer tokenizer = new StringTokenizer(list, ", "); //$NON-NLS-1$
- while (tokenizer.hasMoreTokens()) {
- String token = tokenizer.nextToken();
+ String[] tokens = list.split(", *"); //$NON-NLS-1$
+ for (String token : tokens) {
int tlen = token.length();
if (plen > tlen
&& pkg.startsWith(token)
diff --git a/libcore/luni/src/main/java/java/net/DatagramSocketImpl.java b/libcore/luni/src/main/java/java/net/DatagramSocketImpl.java
index db3b9ec..12b2079 100644
--- a/libcore/luni/src/main/java/java/net/DatagramSocketImpl.java
+++ b/libcore/luni/src/main/java/java/net/DatagramSocketImpl.java
@@ -104,17 +104,6 @@
}
/**
- * Gets the value for the specified socket option.
- *
- * @param optID
- * the ID of the socket option to be retrieved.
- * @return the requested option value.
- * @throws SocketException
- * if an error occurs while accessing the option.
- */
- public abstract Object getOption(int optID) throws SocketException;
-
- /**
* Gets the time-to-live (TTL) for multicast packets sent on this socket.
*
* @return the time-to-live option as a byte value.
@@ -232,19 +221,6 @@
protected abstract void send(DatagramPacket pack) throws IOException;
/**
- * Sets the value for the specified socket option.
- *
- * @param optID
- * the ID of the socket option to be set.
- * @param val
- * the value of the option.
- * @throws SocketException
- * if an error occurs while setting the option.
- */
- public abstract void setOption(int optID, Object val)
- throws SocketException;
-
- /**
* Sets the time-to-live (TTL) option for multicast packets sent on this
* socket.
*
diff --git a/libcore/luni/src/main/java/java/net/InetAddress.java b/libcore/luni/src/main/java/java/net/InetAddress.java
index 33c25f3..c844d54 100644
--- a/libcore/luni/src/main/java/java/net/InetAddress.java
+++ b/libcore/luni/src/main/java/java/net/InetAddress.java
@@ -1320,6 +1320,10 @@
family = fields.get("family", 2); //$NON-NLS-1$
}
+ /*
+ * The spec requires that if we encounter a generic InetAddress in
+ * serialized form then we should interpret it as an Inet4 address.
+ */
private Object readResolve() throws ObjectStreamException {
return new Inet4Address(ipaddress, hostName);
}
diff --git a/libcore/luni/src/main/java/java/net/JarURLConnection.java b/libcore/luni/src/main/java/java/net/JarURLConnection.java
index da39d9c..f41ef64 100644
--- a/libcore/luni/src/main/java/java/net/JarURLConnection.java
+++ b/libcore/luni/src/main/java/java/net/JarURLConnection.java
@@ -69,7 +69,7 @@
if ((sepIdx = file.indexOf("!/")) < 0) { //$NON-NLS-1$
throw new MalformedURLException();
}
- fileURL = new URL(url.getFile().substring(0,sepIdx)); //$NON-NLS-1$
+ fileURL = new URL(url.getFile().substring(0,sepIdx));
sepIdx += 2;
if (file.length() == sepIdx) {
return;
diff --git a/libcore/luni/src/main/java/java/net/NetworkInterface.java b/libcore/luni/src/main/java/java/net/NetworkInterface.java
index 091eb9f..f921b07 100644
--- a/libcore/luni/src/main/java/java/net/NetworkInterface.java
+++ b/libcore/luni/src/main/java/java/net/NetworkInterface.java
@@ -334,67 +334,66 @@
* the object to compare with this instance.
* @return {@code true} if the specified object is equal to this {@code
* NetworkInterface}, {@code false} otherwise.
- * @see #hashCode
+ * @see #hashCode()
*/
@Override
public boolean equals(Object obj) {
- // just return true if it is the exact same object
+ // Return true if it is the exact same object.
if (obj == this) {
return true;
}
- if (obj instanceof NetworkInterface) {
- /*
- * make sure that some simple checks pass. If the name is not the
- * same then we are sure it is not the same one. We don't check the
- * hashcode as it is generated from the name which we check
- */
- NetworkInterface netif = (NetworkInterface) obj;
-
- if (netif.getIndex() != interfaceIndex) {
- return false;
- }
-
- if (!(name.equals("")) && (!netif.getName().equals(name))) { //$NON-NLS-1$
- return false;
- }
-
- if ((name.equals("")) && (!netif.getName().equals(displayName))) { //$NON-NLS-1$
- return false;
- }
-
- // now check that the internet addresses are the same
- Enumeration<InetAddress> netifAddresses = netif.getInetAddresses();
- Enumeration<InetAddress> localifAddresses = getInetAddresses();
- if ((netifAddresses == null) && (localifAddresses != null)) {
- return false;
- }
-
- if ((netifAddresses == null) && (localifAddresses == null)) {
- // neither have any addresses so they are the same
- return true;
- }
-
- if (netifAddresses != null) {
- while (netifAddresses.hasMoreElements()
- && localifAddresses.hasMoreElements()) {
- if (!(localifAddresses.nextElement()).equals(netifAddresses
- .nextElement())) {
- return false;
- }
- }
- /*
- * now make sure that they had the same number of internet
- * addresses, if not they are not the same interface
- */
- if (netifAddresses.hasMoreElements()
- || localifAddresses.hasMoreElements()) {
- return false;
- }
- }
- return true;
+ // Ensure it is the right type.
+ if (!(obj instanceof NetworkInterface)) {
+ return false;
}
- return false;
+
+ /*
+ * Make sure that some simple checks pass. If the name is not the same
+ * then we are sure it is not the same one. We don't check the hashcode
+ * as it is generated from the name which we check
+ */
+ NetworkInterface netif = (NetworkInterface) obj;
+
+ if (netif.getIndex() != interfaceIndex) {
+ return false;
+ }
+
+ if (!(name.equals("")) && (!netif.getName().equals(name))) { //$NON-NLS-1$
+ return false;
+ }
+
+ if ((name.equals("")) && (!netif.getName().equals(displayName))) { //$NON-NLS-1$
+ return false;
+ }
+
+ // Now check that the collection of internet addresses are equal.
+ Enumeration<InetAddress> netifAddresses = netif.getInetAddresses();
+ Enumeration<InetAddress> localifAddresses = getInetAddresses();
+
+ // Check for both null (same), or one null (not same).
+ if (netifAddresses == null) {
+ return localifAddresses == null;
+ }
+ if (localifAddresses == null) {
+ return false;
+ }
+
+ // Both are not null, check InetAddress elements.
+ while (netifAddresses.hasMoreElements()
+ && localifAddresses.hasMoreElements()) {
+ if (!(localifAddresses.nextElement()).equals(
+ netifAddresses.nextElement())) {
+ return false;
+ }
+ }
+
+ /*
+ * Now make sure that they had the same number of addresses, if not they
+ * are not the same interface.
+ */
+ return !netifAddresses.hasMoreElements()
+ && !localifAddresses.hasMoreElements();
}
/**
diff --git a/libcore/luni/src/main/java/java/net/SocketAddress.java b/libcore/luni/src/main/java/java/net/SocketAddress.java
index 32a4c36..e84ebfd 100644
--- a/libcore/luni/src/main/java/java/net/SocketAddress.java
+++ b/libcore/luni/src/main/java/java/net/SocketAddress.java
@@ -26,6 +26,8 @@
*/
public abstract class SocketAddress implements Serializable {
+ private static final long serialVersionUID = 5215720748342549866L;
+
/**
* Creates a new {@code SocketAddress} instance.
*/
diff --git a/libcore/luni/src/main/java/java/net/URL.java b/libcore/luni/src/main/java/java/net/URL.java
index 9b0fdc4..b9e657d 100644
--- a/libcore/luni/src/main/java/java/net/URL.java
+++ b/libcore/luni/src/main/java/java/net/URL.java
@@ -889,15 +889,15 @@
protected void set(String protocol, String host, int port,
String authority, String userInfo, String path, String query,
String ref) {
- String file = path;
+ String filePart = path;
if (query != null && !query.equals("")) { //$NON-NLS-1$
- if (file != null) {
- file = file + "?" + query; //$NON-NLS-1$
+ if (filePart != null) {
+ filePart = filePart + "?" + query; //$NON-NLS-1$
} else {
- file = "?" + query; //$NON-NLS-1$
+ filePart = "?" + query; //$NON-NLS-1$
}
}
- set(protocol, host, port, file, ref);
+ set(protocol, host, port, filePart, ref);
this.authority = authority;
this.userInfo = userInfo;
this.path = path;
diff --git a/libcore/luni/src/main/java/java/net/URLClassLoader.java b/libcore/luni/src/main/java/java/net/URLClassLoader.java
index 6dfa385..61841e6 100644
--- a/libcore/luni/src/main/java/java/net/URLClassLoader.java
+++ b/libcore/luni/src/main/java/java/net/URLClassLoader.java
@@ -1167,7 +1167,7 @@
*/
private ArrayList<URL> getInternalURLs(URL root, String classpath) {
// Class-path attribute is composed of space-separated values.
- StringTokenizer tokenizer = new java.util.StringTokenizer(classpath);
+ StringTokenizer tokenizer = new StringTokenizer(classpath);
ArrayList<URL> addedURLs = new ArrayList<URL>();
String file = root.getFile();
int jarIndex = file.lastIndexOf("!/") - 1; //$NON-NLS-1$
@@ -1177,9 +1177,6 @@
System.getProperty("file.separator"), jarIndex) + 1; //$NON-NLS-1$
}
file = file.substring(0, index);
- String protocol = root.getProtocol();
- String host = root.getHost();
- int port = root.getPort();
while (tokenizer.hasMoreElements()) {
String element = tokenizer.nextToken();
if (!element.equals("")) { //$NON-NLS-1$
diff --git a/libcore/luni/src/main/java/java/util/ArrayList.java b/libcore/luni/src/main/java/java/util/ArrayList.java
index b8c7056..7c46e89 100644
--- a/libcore/luni/src/main/java/java/util/ArrayList.java
+++ b/libcore/luni/src/main/java/java/util/ArrayList.java
@@ -15,12 +15,16 @@
* limitations under the License.
*/
+// BEGIN android-note
+// New implementation: simpler and faster than Harmony implementation.
+// BEGIN android-note
+
package java.util;
import java.io.IOException;
+import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
-import java.io.ObjectStreamField;
import java.io.Serializable;
import java.lang.reflect.Array;
@@ -29,37 +33,38 @@
* optional operations adding, removing, and replacing are supported. The
* elements can be any objects.
*
+ * @param <E> The element type of this list.
* @since 1.2
*/
-public class ArrayList<E> extends AbstractList<E> implements List<E>,
- Cloneable, Serializable, RandomAccess {
-
- private static final long serialVersionUID = 8683452581122892189L;
-
- // BEGIN android-added
- /** zero-element array */
- private static final Object[] emptyArray = new Object[0];
- // END android-added
-
- private transient int firstIndex;
-
- private transient int lastIndex;
-
- private transient E[] array;
+public class ArrayList<E> extends AbstractList<E>
+ implements Cloneable, Serializable, RandomAccess {
+ /**
+ * An empty array of objects (to be shared among all empty lists).
+ */
+ private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
/**
- * Constructs a new instance of {@code ArrayList} with zero capacity.
+ * The minimum amount by which the capacity of an ArrayList will increase.
+ * This tuning parameter controls a time-space tradeoff. This value (12)
+ * gives empirically good results and is arguably consistent with the
+ * RI's specified default initial capacity of 10: instead of 10, we start
+ * with 0 (sans allocation) and jump to 12.
*/
- public ArrayList() {
- // BEGIN android-changed
- // default capacity is zero, not ten
- this(0);
- // END android-changed
- }
+ private static final int MIN_CAPACITY_INCREMENT = 12;
+
+ /**
+ * The number of elements in this list.
+ */
+ int size;
+
+ /**
+ * The elements in this list, followed by nulls.
+ */
+ transient Object[] array;
/**
* Constructs a new instance of {@code ArrayList} with the specified
- * capacity.
+ * initial capacity.
*
* @param capacity
* the initial capacity of this {@code ArrayList}.
@@ -68,84 +73,32 @@
if (capacity < 0) {
throw new IllegalArgumentException();
}
- firstIndex = lastIndex = 0;
- array = newElementArray(capacity);
+ array = (capacity == 0 ? EMPTY_OBJECT_ARRAY : new Object[capacity]);
+ }
+
+ /**
+ * Constructs a new {@code ArrayList} instance with zero initial capacity.
+ */
+ public ArrayList() {
+ array = EMPTY_OBJECT_ARRAY;
}
/**
* Constructs a new instance of {@code ArrayList} containing the elements of
- * the specified collection. The initial size of the {@code ArrayList} will
- * be 10% higher than the size of the specified collection.
+ * the specified collection.
*
* @param collection
* the collection of elements to add.
*/
public ArrayList(Collection<? extends E> collection) {
- firstIndex = 0;
- Object[] objects = collection.toArray();
- int size = objects.length;
- array = newElementArray(size + (size / 10));
- System.arraycopy(objects, 0, array, 0, size);
- lastIndex = size;
- modCount = 1;
- }
-
- @SuppressWarnings("unchecked")
- private E[] newElementArray(int size) {
- // BEGIN android-added
- if (size == 0) {
- return (E[])emptyArray;
+ Object[] a = collection.toArray();
+ if (a.getClass() != Object[].class) {
+ Object[] newArray = new Object[a.length];
+ System.arraycopy(a, 0, newArray, 0, a.length);
+ a = newArray;
}
- // END android-added
-
- return (E[]) new Object[size];
- }
-
- /**
- * Inserts the specified object into this {@code ArrayList} at the specified
- * location. The object is inserted before any previous element at the
- * specified location. If the location is equal to the size of this
- * {@code ArrayList}, the object is added at the end.
- *
- * @param location
- * the index at which to insert the object.
- * @param object
- * the object to add.
- * @throws IndexOutOfBoundsException
- * when {@code location < 0 || > size()}
- */
- @Override
- public void add(int location, E object) {
- int size = lastIndex - firstIndex;
- if (0 < location && location < size) {
- if (firstIndex == 0 && lastIndex == array.length) {
- growForInsert(location, 1);
- } else if ((location < size / 2 && firstIndex > 0)
- || lastIndex == array.length) {
- System.arraycopy(array, firstIndex, array, --firstIndex,
- location);
- } else {
- int index = location + firstIndex;
- System.arraycopy(array, index, array, index + 1, size
- - location);
- lastIndex++;
- }
- array[location + firstIndex] = object;
- } else if (location == 0) {
- if (firstIndex == 0) {
- growAtFront(1);
- }
- array[--firstIndex] = object;
- } else if (location == size) {
- if (lastIndex == array.length) {
- growAtEnd(1);
- }
- array[lastIndex++] = object;
- } else {
- throw new IndexOutOfBoundsException();
- }
-
- modCount++;
+ array = a;
+ size = a.length;
}
/**
@@ -155,80 +108,69 @@
* the object to add.
* @return always true
*/
- @Override
- public boolean add(E object) {
- if (lastIndex == array.length) {
- growAtEnd(1);
+ @Override public boolean add(E object) {
+ Object[] a = array;
+ int s = size;
+ if (s == a.length) {
+ Object[] newArray = new Object[s +
+ (s < (MIN_CAPACITY_INCREMENT / 2) ?
+ MIN_CAPACITY_INCREMENT : s >> 1)];
+ System.arraycopy(a, 0, newArray, 0, s);
+ array = a = newArray;
}
- array[lastIndex++] = object;
+ a[s] = object;
+ size = s + 1;
modCount++;
return true;
}
/**
- * Inserts the objects in the specified collection at the specified location
- * in this List. The objects are added in the order they are returned from
- * the collection's iterator.
+ * Inserts the specified object into this {@code ArrayList} at the specified
+ * location. The object is inserted before any previous element at the
+ * specified location. If the location is equal to the size of this
+ * {@code ArrayList}, the object is added at the end.
*
- * @param location
- * the index at which to insert.
- * @param collection
- * the collection of objects.
- * @return {@code true} if this {@code ArrayList} is modified, {@code false}
- * otherwise.
+ * @param index
+ * the index at which to insert the object.
+ * @param object
+ * the object to add.
* @throws IndexOutOfBoundsException
* when {@code location < 0 || > size()}
*/
- @Override
- public boolean addAll(int location, Collection<? extends E> collection) {
- int size = lastIndex - firstIndex;
- if (location < 0 || location > size) {
- throw new IndexOutOfBoundsException();
- }
- if (this == collection) {
- collection = (ArrayList)clone();
- }
- Object[] dumparray = collection.toArray();
- int growSize = dumparray.length;
- if (growSize == 0) {
- return false;
+ @Override public void add(int index, E object) {
+ Object[] a = array;
+ int s = size;
+ if (index > s) {
+ throwIndexOutOfBoundsException(index, s);
}
- if (0 < location && location < size) {
- if (array.length - size < growSize) {
- growForInsert(location, growSize);
- } else if ((location < size / 2 && firstIndex > 0)
- || lastIndex > array.length - growSize) {
- int newFirst = firstIndex - growSize;
- if (newFirst < 0) {
- int index = location + firstIndex;
- System.arraycopy(array, index, array, index - newFirst,
- size - location);
- lastIndex -= newFirst;
- newFirst = 0;
- }
- System.arraycopy(array, firstIndex, array, newFirst, location);
- firstIndex = newFirst;
- } else {
- int index = location + firstIndex;
- System.arraycopy(array, index, array, index + growSize, size
- - location);
- lastIndex += growSize;
- }
- } else if (location == 0) {
- growAtFront(growSize);
- firstIndex -= growSize;
- } else if (location == size) {
- if (lastIndex > array.length - growSize) {
- growAtEnd(growSize);
- }
- lastIndex += growSize;
+ if (s < a.length) {
+ System.arraycopy(a, index, a, index + 1, s - index);
+ } else {
+ // assert s == a.length;
+ Object[] newArray = new Object[newCapacity(s)];
+ System.arraycopy(a, 0, newArray, 0, index);
+ System.arraycopy(a, index, newArray, index + 1, s - index);
+ array = a = newArray;
}
-
- System.arraycopy(dumparray, 0, this.array, location + firstIndex,
- growSize);
+ a[index] = object;
+ size = s + 1;
modCount++;
- return true;
+ }
+
+ /**
+ * This method controls the growth of ArrayList capacities. It represents
+ * a time-space tradeoff: we don't want to grow lists too frequently
+ * (which wastes time and fragments storage), but we don't want to waste
+ * too much space in unused excess capacity.
+ *
+ * NOTE: This method is inlined into {@link #add(Object)} for performance.
+ * If you change the method, change it there too!
+ */
+ private static int newCapacity(int currentCapacity) {
+ int increment = (currentCapacity < (MIN_CAPACITY_INCREMENT / 2) ?
+ MIN_CAPACITY_INCREMENT : currentCapacity >> 1);
+ return currentCapacity + increment;
}
/**
@@ -239,32 +181,85 @@
* @return {@code true} if this {@code ArrayList} is modified, {@code false}
* otherwise.
*/
- @Override
- public boolean addAll(Collection<? extends E> collection) {
- Object[] dumpArray = collection.toArray();
- if (dumpArray.length == 0) {
+ @Override public boolean addAll(Collection<? extends E> collection) {
+ Object[] newPart = collection.toArray();
+ int newPartSize = newPart.length;
+ if (newPartSize == 0) {
return false;
}
- if (dumpArray.length > array.length - lastIndex) {
- growAtEnd(dumpArray.length);
+ Object[] a = array;
+ int s = size;
+ int newSize = s + newPartSize; // If add overflows, arraycopy will fail
+ if (newSize > a.length) {
+ int newCapacity = newCapacity(newSize - 1); // ~33% growth room
+ Object[] newArray = new Object[newCapacity];
+ System.arraycopy(a, 0, newArray, 0, s);
+ array = a = newArray;
}
- System.arraycopy(dumpArray, 0, this.array, lastIndex, dumpArray.length);
- lastIndex += dumpArray.length;
+ System.arraycopy(newPart, 0, a, s, newPartSize);
+ size = newSize;
modCount++;
return true;
}
/**
+ * Inserts the objects in the specified collection at the specified location
+ * in this List. The objects are added in the order they are returned from
+ * the collection's iterator.
+ *
+ * @param index
+ * the index at which to insert.
+ * @param collection
+ * the collection of objects.
+ * @return {@code true} if this {@code ArrayList} is modified, {@code false}
+ * otherwise.
+ * @throws IndexOutOfBoundsException
+ * when {@code location < 0 || > size()}
+ */
+ @Override
+ public boolean addAll(int index, Collection<? extends E> collection) {
+ Object[] newPart = collection.toArray();
+ int newPartSize = newPart.length;
+ if (newPartSize == 0) {
+ return false;
+ }
+ Object[] a = array;
+ int s = size;
+ if (index > s) {
+ throwIndexOutOfBoundsException(index, s);
+ }
+ int newSize = s + newPartSize; // If add overflows, arraycopy will fail
+ if (newSize <= a.length) {
+ System.arraycopy(a, index, a, index + newPartSize, s - index);
+ } else {
+ int newCapacity = newCapacity(newSize - 1); // ~33% growth room
+ Object[] newArray = new Object[newCapacity];
+ System.arraycopy(a, 0, newArray, 0, index);
+ System.arraycopy(a, index, newArray, index + newPartSize, s-index);
+ array = a = newArray;
+ }
+ System.arraycopy(newPart, 0, a, index, newPartSize);
+ size = newSize;
+ modCount++;
+ return true;
+ }
+
+ /** This method was extracted to encourage VM to inline callers. */
+ private static void throwIndexOutOfBoundsException(int index, int size) {
+ throw new IndexOutOfBoundsException("Invalid index " + index
+ + ", size is " + size);
+ }
+
+ /**
* Removes all elements from this {@code ArrayList}, leaving it empty.
*
* @see #isEmpty
* @see #size
*/
- @Override
- public void clear() {
- if (firstIndex != lastIndex) {
- Arrays.fill(array, firstIndex, lastIndex, null);
- firstIndex = lastIndex = 0;
+ @Override public void clear() {
+ if (size != 0) {
+ Arrays.fill(array, 0, size, null);
+ size = 0;
modCount++;
}
}
@@ -276,45 +271,17 @@
* @return a shallow copy of this {@code ArrayList}
* @see java.lang.Cloneable
*/
- @Override
- @SuppressWarnings("unchecked")
- public Object clone() {
+ @Override public Object clone() {
try {
- ArrayList<E> newList = (ArrayList<E>) super.clone();
- newList.array = array.clone();
- return newList;
+ ArrayList<?> result = (ArrayList<?>) super.clone();
+ result.array = array.clone();
+ return result;
} catch (CloneNotSupportedException e) {
- return null;
+ throw new AssertionError();
}
}
/**
- * Searches this {@code ArrayList} for the specified object.
- *
- * @param object
- * the object to search for.
- * @return {@code true} if {@code object} is an element of this
- * {@code ArrayList}, {@code false} otherwise
- */
- @Override
- public boolean contains(Object object) {
- if (object != null) {
- for (int i = firstIndex; i < lastIndex; i++) {
- if (object.equals(array[i])) {
- return true;
- }
- }
- } else {
- for (int i = firstIndex; i < lastIndex; i++) {
- if (array[i] == null) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
* Ensures that after this operation the {@code ArrayList} can hold the
* specified number of elements without further growing.
*
@@ -322,145 +289,93 @@
* the minimum capacity asked for.
*/
public void ensureCapacity(int minimumCapacity) {
- if (array.length < minimumCapacity) {
- if (firstIndex > 0) {
- growAtFront(minimumCapacity - array.length);
- } else {
- growAtEnd(minimumCapacity - array.length);
- }
- }
- }
-
- @Override
- public E get(int location) {
- // BEGIN android-changed: slight performance improvement
- int _firstIndex = firstIndex;
- if (0 <= location && location < lastIndex - _firstIndex) {
- return array[_firstIndex + location];
- }
- throw new IndexOutOfBoundsException("Invalid location " + location
- + ", size is " + (lastIndex - _firstIndex));
- // END android-changed
- }
-
- private void growAtEnd(int required) {
- int size = lastIndex - firstIndex;
- if (firstIndex >= required - (array.length - lastIndex)) {
- int newLast = lastIndex - firstIndex;
- if (size > 0) {
- System.arraycopy(array, firstIndex, array, 0, size);
- int start = newLast < firstIndex ? firstIndex : newLast;
- Arrays.fill(array, start, array.length, null);
- }
- firstIndex = 0;
- lastIndex = newLast;
- } else {
- int increment = size / 2;
- if (required > increment) {
- increment = required;
- }
- if (increment < 12) {
- increment = 12;
- }
- E[] newArray = newElementArray(size + increment);
- if (size > 0) {
- System.arraycopy(array, firstIndex, newArray, 0, size);
- firstIndex = 0;
- lastIndex = size;
- }
+ Object[] a = array;
+ if (a.length < minimumCapacity) {
+ Object[] newArray = new Object[minimumCapacity];
+ System.arraycopy(a, 0, newArray, 0, size);
array = newArray;
+ modCount++;
}
}
- private void growAtFront(int required) {
- int size = lastIndex - firstIndex;
- if (array.length - lastIndex + firstIndex >= required) {
- int newFirst = array.length - size;
- if (size > 0) {
- System.arraycopy(array, firstIndex, array, newFirst, size);
- int length = firstIndex + size > newFirst ? newFirst
- : firstIndex + size;
- Arrays.fill(array, firstIndex, length, null);
- }
- firstIndex = newFirst;
- lastIndex = array.length;
- } else {
- int increment = size / 2;
- if (required > increment) {
- increment = required;
- }
- if (increment < 12) {
- increment = 12;
- }
- E[] newArray = newElementArray(size + increment);
- if (size > 0) {
- System.arraycopy(array, firstIndex, newArray, newArray.length
- - size, size);
- }
- firstIndex = newArray.length - size;
- lastIndex = newArray.length;
- array = newArray;
+ @SuppressWarnings("unchecked") @Override public E get(int index) {
+ if (index >= size) {
+ throwIndexOutOfBoundsException(index, size);
}
+ return (E) array[index];
}
- private void growForInsert(int location, int required) {
- int size = lastIndex - firstIndex;
- int increment = size / 2;
- if (required > increment) {
- increment = required;
- }
- if (increment < 12) {
- increment = 12;
- }
- E[] newArray = newElementArray(size + increment);
- int newFirst = increment - required;
- // Copy elements after location to the new array skipping inserted
- // elements
- System.arraycopy(array, location + firstIndex, newArray, newFirst
- + location + required, size - location);
- // Copy elements before location to the new array from firstIndex
- System.arraycopy(array, firstIndex, newArray, newFirst, location);
- firstIndex = newFirst;
- lastIndex = size + increment;
-
- array = newArray;
+ /**
+ * Returns the number of elements in this {@code ArrayList}.
+ *
+ * @return the number of elements in this {@code ArrayList}.
+ */
+ @Override public int size() {
+ return size;
}
- @Override
- public int indexOf(Object object) {
+ @Override public boolean isEmpty() {
+ return size == 0;
+ }
+
+ /**
+ * Searches this {@code ArrayList} for the specified object.
+ *
+ * @param object
+ * the object to search for.
+ * @return {@code true} if {@code object} is an element of this
+ * {@code ArrayList}, {@code false} otherwise
+ */
+ @Override public boolean contains(Object object) {
+ Object[] a = array;
+ int s = size;
if (object != null) {
- for (int i = firstIndex; i < lastIndex; i++) {
- if (object.equals(array[i])) {
- return i - firstIndex;
+ for (int i = 0; i < s; i++) {
+ if (object.equals(a[i])) {
+ return true;
}
}
} else {
- for (int i = firstIndex; i < lastIndex; i++) {
- if (array[i] == null) {
- return i - firstIndex;
+ for (int i = 0; i < s; i++) {
+ if (a[i] == null) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override public int indexOf(Object object) {
+ Object[] a = array;
+ int s = size;
+ if (object != null) {
+ for (int i = 0; i < s; i++) {
+ if (object.equals(a[i])) {
+ return i;
+ }
+ }
+ } else {
+ for (int i = 0; i < s; i++) {
+ if (a[i] == null) {
+ return i;
}
}
}
return -1;
}
- @Override
- public boolean isEmpty() {
- return lastIndex == firstIndex;
- }
-
- @Override
- public int lastIndexOf(Object object) {
+ @Override public int lastIndexOf(Object object) {
+ Object[] a = array;
if (object != null) {
- for (int i = lastIndex - 1; i >= firstIndex; i--) {
- if (object.equals(array[i])) {
- return i - firstIndex;
+ for (int i = size - 1; i >= 0; i--) {
+ if (object.equals(a[i])) {
+ return i;
}
}
} else {
- for (int i = lastIndex - 1; i >= firstIndex; i--) {
- if (array[i] == null) {
- return i - firstIndex;
+ for (int i = size - 1; i >= 0; i--) {
+ if (a[i] == null) {
+ return i;
}
}
}
@@ -470,99 +385,81 @@
/**
* Removes the object at the specified location from this list.
*
- * @param location
+ * @param index
* the index of the object to remove.
* @return the removed object.
* @throws IndexOutOfBoundsException
* when {@code location < 0 || >= size()}
*/
- @Override
- public E remove(int location) {
- E result;
- int size = lastIndex - firstIndex;
- if (0 <= location && location < size) {
- if (location == size - 1) {
- result = array[--lastIndex];
- array[lastIndex] = null;
- } else if (location == 0) {
- result = array[firstIndex];
- array[firstIndex++] = null;
- } else {
- int elementIndex = firstIndex + location;
- result = array[elementIndex];
- if (location < size / 2) {
- System.arraycopy(array, firstIndex, array, firstIndex + 1,
- location);
- array[firstIndex++] = null;
- } else {
- System.arraycopy(array, elementIndex + 1, array,
- elementIndex, size - location - 1);
- array[--lastIndex] = null;
- }
- }
- if (firstIndex == lastIndex) {
- firstIndex = lastIndex = 0;
- }
- } else {
- throw new IndexOutOfBoundsException();
+ @Override public E remove(int index) {
+ Object[] a = array;
+ int s = size;
+ if (index >= s) {
+ throwIndexOutOfBoundsException(index, s);
}
-
+ @SuppressWarnings("unchecked") E result = (E) a[index];
+ System.arraycopy(a, index + 1, a, index, --s - index);
+ a[s] = null; // Prevent memory leak
+ size = s;
modCount++;
return result;
}
- @Override
- public boolean remove(Object object) {
- int location = indexOf(object);
- if (location >= 0) {
- remove(location);
- return true;
+ @Override public boolean remove(Object object) {
+ Object[] a = array;
+ int s = size;
+ if (object != null) {
+ for (int i = 0; i < s; i++) {
+ if (object.equals(a[i])) {
+ System.arraycopy(a, i + 1, a, i, --s - i);
+ a[s] = null; // Prevent memory leak
+ size = s;
+ modCount++;
+ return true;
+ }
+ }
+ } else {
+ for (int i = 0; i < s; i++) {
+ if (a[i] == null) {
+ System.arraycopy(a, i + 1, a, i, --s - i);
+ a[s] = null; // Prevent memory leak
+ size = s;
+ modCount++;
+ return true;
+ }
+ }
}
return false;
}
- /**
- * Removes the objects in the specified range from the start to the end, but
- * not including the end index.
- *
- * @param start
- * the index at which to start removing.
- * @param end
- * the index one after the end of the range to remove.
- * @throws IndexOutOfBoundsException
- * when {@code start < 0, start > end} or {@code end > size()}
- */
- @Override
- protected void removeRange(int start, int end) {
- if (start >= 0 && start <= end && end <= (lastIndex - firstIndex)) {
- if (start == end) {
- return;
- }
- int size = lastIndex - firstIndex;
- if (end == size) {
- Arrays.fill(array, firstIndex + start, lastIndex, null);
- lastIndex = firstIndex + start;
- } else if (start == 0) {
- Arrays.fill(array, firstIndex, firstIndex + end, null);
- firstIndex += end;
- } else {
- System.arraycopy(array, firstIndex + end, array, firstIndex
- + start, size - end);
- int newLast = lastIndex + start - end;
- Arrays.fill(array, newLast, lastIndex, null);
- lastIndex = newLast;
- }
- modCount++;
- } else {
- throw new IndexOutOfBoundsException();
+ @Override protected void removeRange(int fromIndex, int toIndex) {
+ Object[] a = array;
+ int s = size;
+ if (fromIndex >= s) {
+ throw new IndexOutOfBoundsException("fromIndex " + fromIndex
+ + " >= size " + size);
}
+ if (toIndex > s) {
+ throw new IndexOutOfBoundsException("toIndex " + toIndex
+ + " > size " + size);
+ }
+ if (fromIndex > toIndex) {
+ throw new IndexOutOfBoundsException("fromIndex " + fromIndex
+ + " > toIndex " + toIndex);
+ }
+
+ System.arraycopy(a, toIndex, a, fromIndex, s - toIndex);
+ int rangeSize = toIndex - fromIndex;
+ Arrays.fill(a, s - rangeSize, s, null);
+ size = s - rangeSize;
+ modCount++;
}
/**
* Replaces the element at the specified location in this {@code ArrayList}
* with the specified object.
*
- * @param location
+ * @param index
* the index at which to put the specified object.
* @param object
* the object to add.
@@ -570,24 +467,14 @@
* @throws IndexOutOfBoundsException
* when {@code location < 0 || >= size()}
*/
- @Override
- public E set(int location, E object) {
- if (0 <= location && location < (lastIndex - firstIndex)) {
- E result = array[firstIndex + location];
- array[firstIndex + location] = object;
- return result;
+ @Override public E set(int index, E object) {
+ Object[] a = array;
+ if (index >= size) {
+ throwIndexOutOfBoundsException(index, size);
}
- throw new IndexOutOfBoundsException();
- }
-
- /**
- * Returns the number of elements in this {@code ArrayList}.
- *
- * @return the number of elements in this {@code ArrayList}.
- */
- @Override
- public int size() {
- return lastIndex - firstIndex;
+ @SuppressWarnings("unchecked") E result = (E) a[index];
+ a[index] = object;
+ return result;
}
/**
@@ -596,11 +483,10 @@
*
* @return an array of the elements from this {@code ArrayList}
*/
- @Override
- public Object[] toArray() {
- int size = lastIndex - firstIndex;
- Object[] result = new Object[size];
- System.arraycopy(array, firstIndex, result, 0, size);
+ @Override public Object[] toArray() {
+ int s = size;
+ Object[] result = new Object[s];
+ System.arraycopy(array, 0, result, 0, s);
return result;
}
@@ -619,17 +505,16 @@
* when the type of an element in this {@code ArrayList} cannot
* be stored in the type of the specified array.
*/
- @Override
- @SuppressWarnings("unchecked")
- public <T> T[] toArray(T[] contents) {
- int size = lastIndex - firstIndex;
- if (size > contents.length) {
- Class<?> ct = contents.getClass().getComponentType();
- contents = (T[]) Array.newInstance(ct, size);
+ @Override public <T> T[] toArray(T[] contents) {
+ int s = size;
+ if (contents.length < s) {
+ @SuppressWarnings("unchecked") T[] newArray
+ = (T[]) Array.newInstance(contents.getClass().getComponentType(), s);
+ contents = newArray;
}
- System.arraycopy(array, firstIndex, contents, 0, size);
- if (size < contents.length) {
- contents[size] = null;
+ System.arraycopy(this.array, 0, contents, 0, s);
+ if (contents.length > s) {
+ contents[s] = null;
}
return contents;
}
@@ -641,37 +526,132 @@
* @see #size
*/
public void trimToSize() {
- int size = lastIndex - firstIndex;
- E[] newArray = newElementArray(size);
- System.arraycopy(array, firstIndex, newArray, 0, size);
- array = newArray;
- firstIndex = 0;
- lastIndex = array.length;
- modCount = 0;
+ int s = size;
+ if (s == array.length) {
+ return;
+ }
+ if (s == 0) {
+ array = EMPTY_OBJECT_ARRAY;
+ } else {
+ Object[] newArray = new Object[s];
+ System.arraycopy(array, 0, newArray, 0, s);
+ array = newArray;
+ }
+ modCount++;
}
- private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField(
- "size", Integer.TYPE) }; //$NON-NLS-1$
+ @Override public Iterator<E> iterator() {
+ return new ArrayListIterator();
+ }
+
+ private class ArrayListIterator implements Iterator<E> {
+ /** Number of elements remaining in this iteration */
+ private int remaining = size;
+
+ /** Index of element that remove() would remove, or -1 if no such elt */
+ private int removalIndex = -1;
+
+ /** The expected modCount value */
+ private int expectedModCount = modCount;
+
+ public boolean hasNext() {
+ return remaining != 0;
+ }
+
+ @SuppressWarnings("unchecked") public E next() {
+ ArrayList<E> ourList = ArrayList.this;
+ int rem = remaining;
+ if (ourList.modCount != expectedModCount) {
+ throw new ConcurrentModificationException();
+ }
+ if (rem == 0) {
+ throw new NoSuchElementException();
+ }
+ remaining = rem - 1;
+ return (E) ourList.array[removalIndex = ourList.size - rem];
+ }
+
+ public void remove() {
+ Object[] a = array;
+ int removalIdx = removalIndex;
+ if (modCount != expectedModCount) {
+ throw new ConcurrentModificationException();
+ }
+ if (removalIdx < 0) {
+ throw new IllegalStateException();
+ }
+ System.arraycopy(a, removalIdx + 1, a, removalIdx, remaining);
+ a[--size] = null; // Prevent memory leak
+ removalIndex = -1;
+ expectedModCount = ++modCount;
+ }
+ }
+
+ @Override public int hashCode() {
+ Object[] a = array;
+ int hashCode = 1;
+ for (int i = 0, s = size; i < s; i++) {
+ Object e = a[i];
+ hashCode = 31 * hashCode + (e == null ? 0 : e.hashCode());
+ }
+ return hashCode;
+ }
+
+ @Override public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof List)) {
+ return false;
+ }
+ List<?> that = (List<?>) o;
+ int s = size;
+ if (that.size() != s) {
+ return false;
+ }
+ Object[] a = array;
+ if (that instanceof RandomAccess) {
+ for (int i = 0; i < s; i++) {
+ Object eThis = a[i];
+ Object ethat = that.get(i);
+ if (eThis == null ? ethat != null : !eThis.equals(ethat)) {
+ return false;
+ }
+ }
+ } else { // Argument list is not random access; use its iterator
+ Iterator<?> it = that.iterator();
+ for (int i = 0; i < s; i++) {
+ Object eThis = a[i];
+ Object eThat = it.next();
+ if (eThis == null ? eThat != null : !eThis.equals(eThat)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private static final long serialVersionUID = 8683452581122892189L;
private void writeObject(ObjectOutputStream stream) throws IOException {
- ObjectOutputStream.PutField fields = stream.putFields();
- fields.put("size", lastIndex - firstIndex); //$NON-NLS-1$
- stream.writeFields();
+ stream.defaultWriteObject();
stream.writeInt(array.length);
- Iterator<?> it = iterator();
- while (it.hasNext()) {
- stream.writeObject(it.next());
+ for (int i = 0; i < size; i++) {
+ stream.writeObject(array[i]);
}
}
- @SuppressWarnings("unchecked")
private void readObject(ObjectInputStream stream) throws IOException,
ClassNotFoundException {
- ObjectInputStream.GetField fields = stream.readFields();
- lastIndex = fields.get("size", 0); //$NON-NLS-1$
- array = newElementArray(stream.readInt());
- for (int i = 0; i < lastIndex; i++) {
- array[i] = (E) stream.readObject();
+ stream.defaultReadObject();
+ int cap = stream.readInt();
+ if (cap < size) {
+ throw new InvalidObjectException(
+ "Capacity: " + cap + " < size: " + size);
+ }
+ array = (cap == 0 ? EMPTY_OBJECT_ARRAY : new Object[cap]);
+ for (int i = 0; i < size; i++) {
+ array[i] = stream.readObject();
}
}
-}
+ }
diff --git a/libcore/luni/src/main/java/java/util/Arrays.java b/libcore/luni/src/main/java/java/util/Arrays.java
index 4fc1e85..ba03251 100644
--- a/libcore/luni/src/main/java/java/util/Arrays.java
+++ b/libcore/luni/src/main/java/java/util/Arrays.java
@@ -20,6 +20,8 @@
import java.io.Serializable;
import java.lang.reflect.Array;
+import org.apache.harmony.luni.util.Msg;
+
/**
* {@code Arrays} contains static methods which operate on arrays.
*
@@ -492,14 +494,7 @@
* if {@code start < 0} or {@code end > array.length}.
*/
public static void fill(byte[] array, int start, int end, byte value) {
- // Check for null first
- int length = array.length;
- if (start > end) {
- throw new IllegalArgumentException();
- }
- if (start < 0 || end > length) {
- throw new ArrayIndexOutOfBoundsException();
- }
+ checkBounds(array.length, start, end);
for (int i = start; i < end; i++) {
array[i] = value;
}
@@ -536,14 +531,7 @@
* if {@code start < 0} or {@code end > array.length}.
*/
public static void fill(short[] array, int start, int end, short value) {
- // Check for null first
- int length = array.length;
- if (start > end) {
- throw new IllegalArgumentException();
- }
- if (start < 0 || end > length) {
- throw new ArrayIndexOutOfBoundsException();
- }
+ checkBounds(array.length, start, end);
for (int i = start; i < end; i++) {
array[i] = value;
}
@@ -580,14 +568,7 @@
* if {@code start < 0} or {@code end > array.length}.
*/
public static void fill(char[] array, int start, int end, char value) {
- // Check for null first
- int length = array.length;
- if (start > end) {
- throw new IllegalArgumentException();
- }
- if (start < 0 || end > length) {
- throw new ArrayIndexOutOfBoundsException();
- }
+ checkBounds(array.length, start, end);
for (int i = start; i < end; i++) {
array[i] = value;
}
@@ -624,14 +605,7 @@
* if {@code start < 0} or {@code end > array.length}.
*/
public static void fill(int[] array, int start, int end, int value) {
- // Check for null first
- int length = array.length;
- if (start > end) {
- throw new IllegalArgumentException();
- }
- if (start < 0 || end > length) {
- throw new ArrayIndexOutOfBoundsException();
- }
+ checkBounds(array.length, start, end);
for (int i = start; i < end; i++) {
array[i] = value;
}
@@ -668,14 +642,7 @@
* if {@code start < 0} or {@code end > array.length}.
*/
public static void fill(long[] array, int start, int end, long value) {
- // Check for null first
- int length = array.length;
- if (start > end) {
- throw new IllegalArgumentException();
- }
- if (start < 0 || end > length) {
- throw new ArrayIndexOutOfBoundsException();
- }
+ checkBounds(array.length, start, end);
for (int i = start; i < end; i++) {
array[i] = value;
}
@@ -712,14 +679,7 @@
* if {@code start < 0} or {@code end > array.length}.
*/
public static void fill(float[] array, int start, int end, float value) {
- // Check for null first
- int length = array.length;
- if (start > end) {
- throw new IllegalArgumentException();
- }
- if (start < 0 || end > length) {
- throw new ArrayIndexOutOfBoundsException();
- }
+ checkBounds(array.length, start, end);
for (int i = start; i < end; i++) {
array[i] = value;
}
@@ -756,14 +716,7 @@
* if {@code start < 0} or {@code end > array.length}.
*/
public static void fill(double[] array, int start, int end, double value) {
- // Check for null first
- int length = array.length;
- if (start > end) {
- throw new IllegalArgumentException();
- }
- if (start < 0 || end > length) {
- throw new ArrayIndexOutOfBoundsException();
- }
+ checkBounds(array.length, start, end);
for (int i = start; i < end; i++) {
array[i] = value;
}
@@ -800,14 +753,7 @@
* if {@code start < 0} or {@code end > array.length}.
*/
public static void fill(boolean[] array, int start, int end, boolean value) {
- // Check for null first
- int length = array.length;
- if (start > end) {
- throw new IllegalArgumentException();
- }
- if (start < 0 || end > length) {
- throw new ArrayIndexOutOfBoundsException();
- }
+ checkBounds(array.length, start, end);
for (int i = start; i < end; i++) {
array[i] = value;
}
@@ -844,14 +790,7 @@
* if {@code start < 0} or {@code end > array.length}.
*/
public static void fill(Object[] array, int start, int end, Object value) {
- // Check for null first
- int length = array.length;
- if (start > end) {
- throw new IllegalArgumentException();
- }
- if (start < 0 || end > length) {
- throw new ArrayIndexOutOfBoundsException();
- }
+ checkBounds(array.length, start, end);
for (int i = start; i < end; i++) {
array[i] = value;
}
@@ -1690,11 +1629,17 @@
private static void checkBounds(int arrLength, int start, int end) {
if (start > end) {
- throw new IllegalArgumentException("start(" + start //$NON-NLS-1$
- + ") > end(" + end + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+ // K0033=Start index ({0}) is greater than end index ({1})
+ throw new IllegalArgumentException(Msg.getString("K0033", //$NON-NLS-1$
+ Integer.valueOf(start), Integer.valueOf(end)));
}
- if (start < 0 || end > arrLength) {
- throw new ArrayIndexOutOfBoundsException();
+ if (start < 0) {
+ // K0052=Array index out of range\: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K0052", start)); //$NON-NLS-1$
+ }
+ if (end > arrLength) {
+ // K0052=Array index out of range\: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K0052", end)); //$NON-NLS-1$
}
}
diff --git a/libcore/luni/src/main/java/java/util/Collection.java b/libcore/luni/src/main/java/java/util/Collection.java
index 6447e39..1b5cff5 100644
--- a/libcore/luni/src/main/java/java/util/Collection.java
+++ b/libcore/luni/src/main/java/java/util/Collection.java
@@ -24,7 +24,7 @@
* of {@code Collection}s.
*
* All direct or indirect implementations of {@code Collection} should implement at
- * least two constuctors. One with no parameters which creates an empty
+ * least two constructors. One with no parameters which creates an empty
* collection and one with a parameter of type {@code Collection}. This second
* constructor can be used to create a collection of different type as the
* initial collection but with the same elements. Implementations of {@code Collection}
@@ -138,7 +138,7 @@
/**
* Tests whether this {@code Collection} contains all objects contained in the
- * specified {@code Collection}. If an elemenet {@code elem} is contained several
+ * specified {@code Collection}. If an element {@code elem} is contained several
* times in the specified {@code Collection}, the method returns {@code true} even
* if {@code elem} is contained only once in this {@code Collection}.
*
diff --git a/libcore/luni/src/main/java/java/util/Collections.java b/libcore/luni/src/main/java/java/util/Collections.java
index 767d98b..77cafea 100644
--- a/libcore/luni/src/main/java/java/util/Collections.java
+++ b/libcore/luni/src/main/java/java/util/Collections.java
@@ -23,6 +23,7 @@
import java.lang.reflect.Array;
import org.apache.harmony.luni.internal.nls.Messages;
+import org.apache.harmony.luni.util.Msg;
/**
* {@code Collections} contains static methods which operate on
@@ -1590,7 +1591,8 @@
public static <T> void copy(List<? super T> destination,
List<? extends T> source) {
if (destination.size() < source.size()) {
- throw new ArrayIndexOutOfBoundsException();
+ // K0032=Source size {0} does not fit into destination
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K0032", source.size())); //$NON-NLS-1$
}
Iterator<? extends T> srcIt = source.iterator();
ListIterator<? super T> destIt = destination.listIterator();
@@ -1598,7 +1600,8 @@
try {
destIt.next();
} catch (NoSuchElementException e) {
- throw new ArrayIndexOutOfBoundsException();
+ // K0032=Source size {0} does not fit into destination
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K0032", source.size())); //$NON-NLS-1$
}
destIt.set(srcIt.next());
}
@@ -1841,36 +1844,30 @@
* @throws UnsupportedOperationException
* when replacing an element in the list is not supported.
*/
- @SuppressWarnings("unchecked")
public static void shuffle(List<?> list, Random random) {
- if (!(list instanceof RandomAccess)) {
- Object[] array = list.toArray();
+ @SuppressWarnings("unchecked") // we won't put foreign objects in
+ final List<Object> objectList = (List<Object>) list;
+
+ if (list instanceof RandomAccess) {
+ for (int i = objectList.size() - 1; i > 0; i--) {
+ int index = random.nextInt(i + 1);
+ objectList.set(index, objectList.set(i, objectList.get(index)));
+ }
+ } else {
+ Object[] array = objectList.toArray();
for (int i = array.length - 1; i > 0; i--) {
int index = random.nextInt(i + 1);
- if (index < 0) {
- index = -index;
- }
Object temp = array[i];
array[i] = array[index];
array[index] = temp;
}
int i = 0;
- ListIterator<Object> it = (ListIterator<Object>) list
- .listIterator();
+ ListIterator<Object> it = objectList.listIterator();
while (it.hasNext()) {
it.next();
it.set(array[i++]);
}
- } else {
- List<Object> rawList = (List<Object>) list;
- for (int i = rawList.size() - 1; i > 0; i--) {
- int index = random.nextInt(i + 1);
- if (index < 0) {
- index = -index;
- }
- rawList.set(index, rawList.set(i, rawList.get(index)));
- }
}
}
diff --git a/libcore/luni/src/main/java/java/util/Formatter.java b/libcore/luni/src/main/java/java/util/Formatter.java
index d1dd417..912a15e 100644
--- a/libcore/luni/src/main/java/java/util/Formatter.java
+++ b/libcore/luni/src/main/java/java/util/Formatter.java
@@ -885,7 +885,6 @@
if (transformer == null || ! transformer.locale.equals(l)) {
transformer = new Transformer(this, l);
}
- // END android-changed
int currentObjectIndex = 0;
Object lastArgument = null;
@@ -893,12 +892,13 @@
while (formatBuffer.hasRemaining()) {
parser.reset();
FormatToken token = parser.getNextFormatToken();
- String result;
String plainText = token.getPlainText();
if (token.getConversionType() == (char) FormatToken.UNSET) {
- result = plainText;
+ outputCharSequence(plainText);
} else {
plainText = plainText.substring(0, plainText.indexOf('%'));
+ outputCharSequence(plainText);
+
Object argument = null;
if (token.requireArgument()) {
int index = token.getArgIndex() == FormatToken.UNSET ? currentObjectIndex++
@@ -908,21 +908,26 @@
lastArgument = argument;
hasLastArgumentSet = true;
}
- result = transformer.transform(token, argument);
- result = (null == result ? plainText : plainText + result);
- }
- // if output is made by formattable callback
- if (null != result) {
- try {
- out.append(result);
- } catch (IOException e) {
- lastIOException = e;
- }
+ outputCharSequence(transformer.transform(token, argument));
}
}
+ // END android-changed
return this;
}
+ // BEGIN android-added
+ // Fixes http://code.google.com/p/android/issues/detail?id=1767.
+ private void outputCharSequence(CharSequence cs) {
+ if (cs != null) {
+ try {
+ out.append(cs);
+ } catch (IOException e) {
+ lastIOException = e;
+ }
+ }
+ }
+ // END android-added
+
private Object getArgument(Object[] args, int index, FormatToken token,
Object lastArgument, boolean hasLastArgumentSet) {
if (index == FormatToken.LAST_ARGUMENT_INDEX && !hasLastArgumentSet) {
@@ -1184,13 +1189,13 @@
* Gets the formatted string according to the format token and the
* argument.
*/
- String transform(FormatToken token, Object argument) {
+ CharSequence transform(FormatToken token, Object argument) {
/* init data member to print */
this.formatToken = token;
this.arg = argument;
- String result;
+ CharSequence result;
switch (token.getConversionType()) {
case 'B':
case 'b': {
@@ -1254,7 +1259,7 @@
if (Character.isUpperCase(token.getConversionType())) {
if (null != result) {
- result = result.toUpperCase(Locale.US);
+ result = result.toString().toUpperCase(Locale.US);
}
}
return result;
@@ -1263,7 +1268,7 @@
/*
* Transforms the Boolean argument to a formatted string.
*/
- private String transformFromBoolean() {
+ private CharSequence transformFromBoolean() {
StringBuilder result = new StringBuilder();
int startIndex = 0;
int flags = formatToken.getFlags();
@@ -1294,7 +1299,7 @@
/*
* Transforms the hashcode of the argument to a formatted string.
*/
- private String transformFromHashCode() {
+ private CharSequence transformFromHashCode() {
StringBuilder result = new StringBuilder();
int startIndex = 0;
@@ -1324,7 +1329,7 @@
/*
* Transforms the String to a formatted string.
*/
- private String transformFromString() {
+ private CharSequence transformFromString() {
StringBuilder result = new StringBuilder();
int startIndex = 0;
int flags = formatToken.getFlags();
@@ -1374,7 +1379,7 @@
/*
* Transforms the Character to a formatted string.
*/
- private String transformFromCharacter() {
+ private CharSequence transformFromCharacter() {
StringBuilder result = new StringBuilder();
int startIndex = 0;
@@ -1434,7 +1439,7 @@
* Transforms percent to a formatted string. Only '-' is legal flag.
* Precision is illegal.
*/
- private String transformFromPercent() {
+ private CharSequence transformFromPercent() {
StringBuilder result = new StringBuilder("%"); //$NON-NLS-1$
int startIndex = 0;
@@ -1462,7 +1467,7 @@
* Transforms line separator to a formatted string. Any flag, the width
* or the precision is illegal.
*/
- private String transformFromLineSeparator() {
+ private CharSequence transformFromLineSeparator() {
if (formatToken.isPrecisionSet()) {
throw new IllegalFormatPrecisionException(formatToken
.getPrecision());
@@ -1492,7 +1497,7 @@
/*
* Pads characters to the formatted string.
*/
- private String padding(StringBuilder source, int startIndex) {
+ private CharSequence padding(StringBuilder source, int startIndex) {
int start = startIndex;
boolean paddingRight = formatToken
.isFlagSet(FormatToken.FLAG_MINUS);
@@ -1520,7 +1525,7 @@
width = Math.max(source.length(), width);
}
if (length >= width) {
- return source.toString();
+ return source;
}
char[] paddings = new char[width - length];
@@ -1532,13 +1537,13 @@
} else {
source.insert(start, insertString);
}
- return source.toString();
+ return source;
}
/*
* Transforms the Integer to a formatted string.
*/
- private String transformFromInteger() {
+ private CharSequence transformFromInteger() {
int startIndex = 0;
boolean isNegative = false;
StringBuilder result = new StringBuilder();
@@ -1651,7 +1656,7 @@
if (isNegative
&& formatToken.isFlagSet(FormatToken.FLAG_PARENTHESIS)) {
result = wrapParentheses(result);
- return result.toString();
+ return result;
}
if (isNegative && formatToken.isFlagSet(FormatToken.FLAG_ZERO)) {
@@ -1680,7 +1685,7 @@
return result;
}
- private String transformFromSpecialNumber() {
+ private CharSequence transformFromSpecialNumber() {
String source = null;
if (!(arg instanceof Number) || arg instanceof BigDecimal) {
@@ -1713,12 +1718,12 @@
formatToken.setPrecision(FormatToken.UNSET);
formatToken.setFlags(formatToken.getFlags()
& (~FormatToken.FLAG_ZERO));
- source = padding(new StringBuilder(source), 0);
+ return padding(new StringBuilder(source), 0);
}
return source;
}
- private String transformFromNull() {
+ private CharSequence transformFromNull() {
formatToken.setFlags(formatToken.getFlags()
& (~FormatToken.FLAG_ZERO));
return padding(new StringBuilder("null"), 0); //$NON-NLS-1$
@@ -1727,7 +1732,7 @@
/*
* Transforms a BigInteger to a formatted string.
*/
- private String transformFromBigInteger() {
+ private CharSequence transformFromBigInteger() {
int startIndex = 0;
boolean isNegative = false;
StringBuilder result = new StringBuilder();
@@ -1817,7 +1822,7 @@
if (isNegative
&& formatToken.isFlagSet(FormatToken.FLAG_PARENTHESIS)) {
result = wrapParentheses(result);
- return result.toString();
+ return result;
}
if (isNegative && formatToken.isFlagSet(FormatToken.FLAG_ZERO)) {
@@ -1829,7 +1834,7 @@
/*
* Transforms a Float,Double or BigDecimal to a formatted string.
*/
- private String transformFromFloat() {
+ private CharSequence transformFromFloat() {
StringBuilder result = new StringBuilder();
int startIndex = 0;
char currentConversionType = formatToken.getConversionType();
@@ -1883,7 +1888,7 @@
currentConversionType, arg.getClass());
}
- String specialNumberResult = transformFromSpecialNumber();
+ CharSequence specialNumberResult = transformFromSpecialNumber();
if (null != specialNumberResult) {
return specialNumberResult;
}
@@ -1896,7 +1901,7 @@
}
// output result
FloatUtil floatUtil = new FloatUtil(result, formatToken,
- (DecimalFormat) NumberFormat.getInstance(locale), arg);
+ (DecimalFormat) getNumberFormat(), arg);
floatUtil.transform(formatToken, result);
formatToken.setPrecision(FormatToken.UNSET);
@@ -1904,7 +1909,7 @@
if (getDecimalFormatSymbols().getMinusSign() == result.charAt(0)) {
if (formatToken.isFlagSet(FormatToken.FLAG_PARENTHESIS)) {
result = wrapParentheses(result);
- return result.toString();
+ return result;
}
} else {
if (formatToken.isFlagSet(FormatToken.FLAG_SPACE)) {
@@ -1933,7 +1938,7 @@
/*
* Transforms a Date to a formatted string.
*/
- private String transformFromDateTime() {
+ private CharSequence transformFromDateTime() {
int startIndex = 0;
char currentConversionType = formatToken.getConversionType();
@@ -2110,18 +2115,15 @@
} else {
l = b.movePointRight(4).longValue();
- b.movePointLeft(4);
if (d >= Math.pow(10, -4) && d < 1) {
requireScientificRepresentation = false;
precision += 4 - String.valueOf(l).length();
l = b.movePointRight(precision + 1).longValue();
- b.movePointLeft(precision + 1);
if (String.valueOf(l).length() <= formatToken
.getPrecision()) {
precision++;
}
l = b.movePointRight(precision).longValue();
- b.movePointLeft(precision);
if (l >= Math.pow(10, precision - 4)) {
formatToken.setPrecision(precision);
}
diff --git a/libcore/luni/src/main/java/java/util/GregorianCalendar.java b/libcore/luni/src/main/java/java/util/GregorianCalendar.java
index d8cd556..7339151 100644
--- a/libcore/luni/src/main/java/java/util/GregorianCalendar.java
+++ b/libcore/luni/src/main/java/java/util/GregorianCalendar.java
@@ -533,7 +533,6 @@
fields[MINUTE] = (millis % 60);
millis /= 60;
fields[HOUR_OF_DAY] = (millis % 24);
- millis /= 24;
fields[AM_PM] = fields[HOUR_OF_DAY] > 11 ? 1 : 0;
fields[HOUR] = fields[HOUR_OF_DAY] % 12;
diff --git a/libcore/luni/src/main/java/java/util/HashMap.java b/libcore/luni/src/main/java/java/util/HashMap.java
index 28978d4..f79601f 100644
--- a/libcore/luni/src/main/java/java/util/HashMap.java
+++ b/libcore/luni/src/main/java/java/util/HashMap.java
@@ -36,7 +36,7 @@
* @param <V> the type of mapped values
*/
public class HashMap<K, V> extends AbstractMap<K, V>
- implements Cloneable, Serializable, Map<K, V> {
+ implements Cloneable, Serializable {
/**
* Min capacity (other than zero) for a HashMap. Must be a power of two
* greater than 1 (and less than 1 << 30).
diff --git a/libcore/luni/src/main/java/java/util/Locale.java b/libcore/luni/src/main/java/java/util/Locale.java
index b1a1821..3d724d0 100644
--- a/libcore/luni/src/main/java/java/util/Locale.java
+++ b/libcore/luni/src/main/java/java/util/Locale.java
@@ -48,7 +48,9 @@
private static final long serialVersionUID = 9149081749638150636L;
+ // BEGIN android-added
private static volatile Locale[] availableLocales;
+ // END android-added
// Initialize a default which is used during static
// initialization of the default for the platform.
@@ -304,93 +306,6 @@
return false;
}
- // BEGIN android-removed
- // static Locale[] find(String prefix) {
- // int last = prefix.lastIndexOf('/');
- // final String thePackage = prefix.substring(0, last + 1);
- // int length = prefix.length();
- // final String classPrefix = prefix.substring(last + 1, length);
- // Set<String> result = new HashSet<String>();
- // StringTokenizer paths = new StringTokenizer(System.getProperty(
- // "org.apache.harmony.boot.class.path", ""), System.getProperty( //$NON-NLS-1$ //$NON-NLS-2$
- // "path.separator", ";")); //$NON-NLS-1$//$NON-NLS-2$
- // while (paths.hasMoreTokens()) {
- // String nextToken = paths.nextToken();
- // File directory = new File(nextToken);
- // if (directory.exists()) {
- // if (directory.isDirectory()) {
- // String path;
- // try {
- // path = directory.getCanonicalPath();
- // } catch (IOException e) {
- // continue;
- // }
- // File newDir;
- // if (path.charAt(path.length() - 1) == File.separatorChar) {
- // newDir = new File(path + thePackage);
- // } else {
- // newDir = new File(path + File.separatorChar
- // + thePackage);
- // }
- // if (newDir.isDirectory()) {
- // String[] list = newDir.list();
- // for (int i = 0; i < list.length; i++) {
- // String name = list[i];
- // if (name.startsWith(classPrefix)
- // && name.endsWith(".class")) { //$NON-NLS-1$
- // result
- // .add(name.substring(0,
- // name.length() - 6));
- // }
- // }
- // }
- //
- // } else {
- // // Handle ZIP/JAR files.
- // try {
- // ZipFile zip = new ZipFile(directory);
- // Enumeration<? extends ZipEntry> entries = zip.entries();
- // while (entries.hasMoreElements()) {
- // ZipEntry e = entries.nextElement();
- // String name = e.getName();
- // if (name.startsWith(prefix)
- // && name.endsWith(".class")) {//$NON-NLS-1$
- // result.add(name.substring(last + 1, name
- // .length() - 6));
- // }
- // }
- // zip.close();
- // } catch (IOException e) {
- // // Empty
- // }
- // }
- // }
- // }
- // Locale[] locales = new Locale[result.size()];
- // int i = 0;
- // for (String name : result) {
- // int index = name.indexOf('_');
- // int nextIndex = name.indexOf('_', index + 1);
- // if (nextIndex == -1) {
- // locales[i++] = new Locale(name.substring(index + 1, name
- // .length()), ""); //$NON-NLS-1$
- // } else {
- // String language = name.substring(index + 1, nextIndex);
- // String variant;
- // if ((index = name.indexOf('_', nextIndex + 1)) == -1) {
- // variant = ""; //$NON-NLS-1$
- // index = name.length();
- // } else {
- // variant = name.substring(index + 1, name.length());
- // }
- // String country = name.substring(nextIndex + 1, index);
- // locales[i++] = new Locale(language, country, variant);
- // }
- // }
- // return locales;
- // }
- // END android-removed
-
// BEGIN android-added
static Locale[] find() {
String[] locales = Resources.getAvailableLocales();
diff --git a/libcore/luni/src/main/java/java/util/Random.java b/libcore/luni/src/main/java/java/util/Random.java
index be27258..f893020 100644
--- a/libcore/luni/src/main/java/java/util/Random.java
+++ b/libcore/luni/src/main/java/java/util/Random.java
@@ -52,15 +52,22 @@
*/
private double nextNextGaussian;
+ // BEGIN android-changed
/**
- * Construct a random generator with the current time of day in milliseconds
- * as the initial state.
+ * Constructs a random generator with an initial state that is
+ * unlikely to be duplicated by a subsequent instantiation.
+ *
+ * <p>The initial state (that is, the seed) is <i>partially</i> based
+ * on the current time of day in milliseconds.</p>
*
* @see #setSeed
*/
public Random() {
- setSeed(System.currentTimeMillis() + hashCode());
+ // Note: Using identityHashCode() to be hermetic wrt subclasses.
+ internalSetSeed(
+ System.currentTimeMillis() + System.identityHashCode(this));
}
+ // END android-changed
/**
* Construct a random generator with the given {@code seed} as the
@@ -72,7 +79,9 @@
* @see #setSeed
*/
public Random(long seed) {
- setSeed(seed);
+ // BEGIN android-changed
+ internalSetSeed(seed);
+ // END android-changed
}
/**
@@ -236,6 +245,7 @@
return ((long) next(32) << 32) + next(32);
}
+ // BEGIN android-changed
/**
* Modifies the seed a using linear congruential formula presented in <i>The
* Art of Computer Programming, Volume 2</i>, Section 3.2.1.
@@ -247,7 +257,20 @@
* @see #Random(long)
*/
public synchronized void setSeed(long seed) {
+ internalSetSeed(seed);
+ }
+
+ /**
+ * Sets the seed. This is used both in the constructor and in the
+ * default implementation of {@link #setSeed}.
+ *
+ * @param seed
+ * the seed that alters the state of the random number
+ * generator.
+ */
+ private void internalSetSeed(long seed) {
this.seed = (seed ^ multiplier) & ((1L << 48) - 1);
haveNextNextGaussian = false;
}
+ // END android-changed
}
diff --git a/libcore/luni/src/main/java/java/util/Scanner.java b/libcore/luni/src/main/java/java/util/Scanner.java
index dd5c024..f1ca423 100644
--- a/libcore/luni/src/main/java/java/util/Scanner.java
+++ b/libcore/luni/src/main/java/java/util/Scanner.java
@@ -1039,7 +1039,7 @@
* Returns the next token if it matches the specified pattern. The token
* will be both prefixed and postfixed by the delimiter that is currently
* being used (or a string that matches the delimiter pattern). This method will block
- * if input is being read. Calling this methos is equivalent to
+ * if input is being read. Calling this method is equivalent to
* {@code next(Pattern.compile(pattern))}.
*
* @param pattern
@@ -1638,7 +1638,7 @@
* Returns a string representation of this {@code Scanner}. The information
* returned may be helpful for debugging. The format of the string is unspecified.
*
- * @return a string represendation of this {@code Scanner}.
+ * @return a string representation of this {@code Scanner}.
*/
@Override
public String toString() {
diff --git a/libcore/luni/src/main/java/java/util/UnknownFormatFlagsException.java b/libcore/luni/src/main/java/java/util/UnknownFormatFlagsException.java
index 2a1b075..66d9076 100644
--- a/libcore/luni/src/main/java/java/util/UnknownFormatFlagsException.java
+++ b/libcore/luni/src/main/java/java/util/UnknownFormatFlagsException.java
@@ -60,6 +60,7 @@
*/
@Override
public String getMessage() {
- return Msg.getString("K034a", flags);
+ // K034a=The flags are {0}
+ return Msg.getString("K034a", flags); //$NON-NLS-1$
}
}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/io/FileCanonPathCache.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/io/FileCanonPathCache.java
index e3ea7b5..c1ffef9 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/io/FileCanonPathCache.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/io/FileCanonPathCache.java
@@ -40,7 +40,7 @@
}
/**
- * Max elemnts could be hold in the cache.
+ * Max elements could be hold in the cache.
*/
public static final int CACHE_SIZE = 256;
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Handler.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Handler.java
index 25d1e69..94719fe 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Handler.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Handler.java
@@ -44,7 +44,7 @@
*/
@Override
protected URLConnection openConnection(URL u) throws IOException {
- return new HttpURLConnection(u, getDefaultPort());
+ return new HttpURLConnectionImpl(u, getDefaultPort());
}
/**
@@ -72,7 +72,7 @@
if (null == u || null == proxy) {
throw new IllegalArgumentException(Msg.getString("K034b")); //$NON-NLS-1$
}
- return new HttpURLConnection(u, getDefaultPort(), proxy);
+ return new HttpURLConnectionImpl(u, getDefaultPort(), proxy);
}
/**
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnectionImpl.java
similarity index 97%
rename from libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java
rename to libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnectionImpl.java
index 2dea92b..1ba7d8c 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnectionImpl.java
@@ -25,6 +25,7 @@
import java.net.Authenticator;
import java.net.CacheRequest;
import java.net.CacheResponse;
+import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
@@ -58,7 +59,7 @@
* such as connecting, sending request and getting the content from the remote
* server.
*/
-public class HttpURLConnection extends java.net.HttpURLConnection {
+public class HttpURLConnectionImpl extends HttpURLConnection {
private static final String POST = "POST"; //$NON-NLS-1$
private static final String GET = "GET"; //$NON-NLS-1$
@@ -280,13 +281,14 @@
@Override
public int read(byte[] buf, int offset, int length) throws IOException {
- if (buf == null) {
- throw new NullPointerException();
+ // Force buf null check first, and avoid int overflow
+ if (offset < 0 || offset > buf.length) {
+ // K002e=Offset out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
}
- // avoid int overflow
- if (offset < 0 || length < 0 || offset > buf.length
- || buf.length - offset < length) {
- throw new ArrayIndexOutOfBoundsException();
+ if (length < 0 || buf.length - offset < length) {
+ // K0031=Length out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
}
if (bytesRemaining <= 0) {
disconnect(false);
@@ -421,13 +423,14 @@
@Override
public int read(byte[] buf, int offset, int length) throws IOException {
- if (buf == null) {
- throw new NullPointerException();
+ // Force buf null check first, and avoid int overflow
+ if (offset > buf.length || offset < 0) {
+ // K002e=Offset out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
}
- // avoid int overflow
- if (offset < 0 || length < 0 || offset > buf.length
- || buf.length - offset < length) {
- throw new ArrayIndexOutOfBoundsException();
+ if (length < 0 || buf.length - offset < length) {
+ // K0031=Length out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", length)); //$NON-NLS-1$
}
if (bytesRemaining <= 0) {
readChunkSize();
@@ -690,7 +693,7 @@
* @param url
* URL The URL this connection is connecting
*/
- protected HttpURLConnection(URL url) {
+ protected HttpURLConnectionImpl(URL url) {
this(url, 80);
}
@@ -702,7 +705,7 @@
* @param port
* int The default connection port
*/
- protected HttpURLConnection(URL url, int port) {
+ protected HttpURLConnectionImpl(URL url, int port) {
super(url);
defaultPort = port;
reqHeader = (Header) defaultReqHeader.clone();
@@ -730,7 +733,7 @@
* @param proxy
* Proxy The proxy which is used to make the connection
*/
- protected HttpURLConnection(URL url, int port, Proxy proxy) {
+ protected HttpURLConnectionImpl(URL url, int port, Proxy proxy) {
this(url, port);
this.proxy = proxy;
}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/Handler.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/Handler.java
index ef68a71..c6bf994 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/Handler.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/Handler.java
@@ -32,7 +32,7 @@
@Override
protected URLConnection openConnection(URL url) throws IOException {
- return new HttpsURLConnection(url, getDefaultPort());
+ return new HttpsURLConnectionImpl(url, getDefaultPort());
}
@Override
@@ -42,7 +42,7 @@
// K034b=url and proxy can not be null
throw new IllegalArgumentException(Msg.getString("K034b")); //$NON-NLS-1$
}
- return new HttpsURLConnection(url, getDefaultPort(), proxy);
+ return new HttpsURLConnectionImpl(url, getDefaultPort(), proxy);
}
@Override
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnection.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnectionImpl.java
similarity index 96%
rename from libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnection.java
rename to libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnectionImpl.java
index 4d0aff7..2ad5b13 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnection.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/https/HttpsURLConnectionImpl.java
@@ -28,16 +28,17 @@
import java.util.List;
import java.util.Map;
+import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSocket;
-import org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnection;
+import org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl;
import org.apache.harmony.luni.internal.nls.Messages;
/**
* HttpsURLConnection implementation.
*/
-public class HttpsURLConnection extends javax.net.ssl.HttpsURLConnection {
+public class HttpsURLConnectionImpl extends HttpsURLConnection {
// Https engine to be wrapped
private final HttpsEngine httpsEngine;
@@ -45,12 +46,12 @@
// SSLSocket to be used for connection
private SSLSocket sslSocket;
- protected HttpsURLConnection(URL url, int port) {
+ protected HttpsURLConnectionImpl(URL url, int port) {
super(url);
httpsEngine = new HttpsEngine(url, port);
}
- protected HttpsURLConnection(URL url, int port, Proxy proxy) {
+ protected HttpsURLConnectionImpl(URL url, int port, Proxy proxy) {
super(url);
httpsEngine = new HttpsEngine(url, port, proxy);
}
@@ -345,7 +346,7 @@
/**
* HttpsEngine
*/
- private class HttpsEngine extends HttpURLConnection {
+ private class HttpsEngine extends HttpURLConnectionImpl {
// In case of using proxy this field indicates
// if it is a SSL Tunnel establishing stage
@@ -364,7 +365,7 @@
if (connected) {
return;
}
- if (usingProxy() && !makingSSLTunnel) {
+ if (super.usingProxy() && !makingSSLTunnel) {
// SSL Tunnel through the proxy was not established yet, do so
makingSSLTunnel = true;
// first - make the connection
@@ -402,7 +403,7 @@
@Override
protected String requestString() {
- if (usingProxy()) {
+ if (super.usingProxy()) {
if (makingSSLTunnel) {
// we are making the SSL Tunneling, return remotehost:port
int port = url.getPort();
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java
index 4db9910..b31cb39 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java
@@ -42,7 +42,7 @@
*/
@Override
protected URLConnection openConnection(URL u) throws IOException {
- return new JarURLConnection(u);
+ return new JarURLConnectionImpl(u);
}
/**
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnection.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnectionImpl.java
similarity index 70%
rename from libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnection.java
rename to libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnectionImpl.java
index 34e7d07..493b768 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnection.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnectionImpl.java
@@ -25,6 +25,7 @@
import java.io.InputStream;
import java.net.ContentHandler;
import java.net.ContentHandlerFactory;
+import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.AccessController;
@@ -42,13 +43,13 @@
import org.apache.harmony.luni.util.Util;
/**
- * This subclass extends <code>URLConnection</code>.
+ * This subclass extends {@code URLConnection}.
* <p>
*
* This class is responsible for connecting and retrieving resources from a Jar
- * file which can be anywhere that can be refered to by an URL.
+ * file which can be anywhere that can be referred to by an URL.
*/
-public class JarURLConnection extends java.net.JarURLConnection {
+public class JarURLConnectionImpl extends JarURLConnection {
static HashMap<URL, JarFile> jarCache = new HashMap<URL, JarFile>();
@@ -62,14 +63,16 @@
private boolean closed;
-
/**
* @param url
* the URL of the JAR
* @throws MalformedURLException
* if the URL is malformed
+ * @throws IOException
+ * if there is a problem opening the connection.
*/
- public JarURLConnection(java.net.URL url) throws MalformedURLException, IOException {
+ public JarURLConnectionImpl(URL url) throws MalformedURLException,
+ IOException {
super(url);
jarFileURL = getJarFileURL();
jarFileURLConnection = jarFileURL.openConnection();
@@ -88,8 +91,8 @@
}
/**
- * Returns the Jar file refered by this <code>URLConnection</code>
- *
+ * Returns the Jar file referred by this {@code URLConnection}.
+ *
* @return the JAR file referenced by this connection
*
* @throws IOException
@@ -103,30 +106,30 @@
}
/**
- * Returns the Jar file refered by this <code>URLConnection</code>
- *
+ * Returns the Jar file referred by this {@code URLConnection}
+ *
* @throws IOException
* if an IO error occurs while connecting to the resource.
*/
private void findJarFile() throws IOException {
JarFile jar = null;
if (getUseCaches()) {
- synchronized(jarCache){
+ synchronized (jarCache) {
jarFile = jarCache.get(jarFileURL);
}
if (jarFile == null) {
jar = openJarFile();
- synchronized(jarCache){
+ synchronized (jarCache) {
jarFile = jarCache.get(jarFileURL);
- if (jarFile == null){
+ if (jarFile == null) {
jarCache.put(jarFileURL, jar);
jarFile = jar;
- }else{
+ } else {
jar.close();
}
}
}
- }else{
+ } else {
jarFile = openJarFile();
}
@@ -135,38 +138,42 @@
}
}
+ @SuppressWarnings("nls")
JarFile openJarFile() throws IOException {
JarFile jar = null;
- if (jarFileURL.getProtocol().equals("file")) { //$NON-NLS-1$
+ if (jarFileURL.getProtocol().equals("file")) {
jar = new JarFile(new File(Util.decode(jarFileURL.getFile(), false,
"UTF-8")), true, ZipFile.OPEN_READ);
} else {
final InputStream is = jarFileURL.openConnection().getInputStream();
try {
jar = AccessController
- .doPrivileged(new PrivilegedAction<JarFile>() {
- public JarFile run() {
- try {
- File tempJar = File.createTempFile("hyjar_", //$NON-NLS-1$
- ".tmp", null); //$NON-NLS-1$
- tempJar.deleteOnExit();
- FileOutputStream fos = new FileOutputStream(
- tempJar);
- byte[] buf = new byte[4096];
- int nbytes = 0;
- while ((nbytes = is.read(buf)) > -1) {
- fos.write(buf, 0, nbytes);
+ .doPrivileged(new PrivilegedAction<JarFile>() {
+ public JarFile run() {
+ try {
+ File tempJar = File.createTempFile(
+ "hyjar_", ".tmp", null);
+ tempJar.deleteOnExit();
+ FileOutputStream fos = new FileOutputStream(
+ tempJar);
+ byte[] buf = new byte[4096];
+ int nbytes = 0;
+ while ((nbytes = is.read(buf)) > -1) {
+ fos.write(buf, 0, nbytes);
+ }
+ fos.close();
+ return new JarFile(tempJar, true,
+ ZipFile.OPEN_READ
+ | ZipFile.OPEN_DELETE);
+ } catch (IOException e) {
+ return null;
}
- fos.close();
- return new JarFile(tempJar,
- true, ZipFile.OPEN_READ | ZipFile.OPEN_DELETE);
- } catch (IOException e) {
- return null;
}
- }
- });
+ });
} finally {
- if (is != null) is.close();
+ if (is != null) {
+ is.close();
+ }
}
}
@@ -174,11 +181,11 @@
}
/**
- * Returns the JarEntry of the entry referenced by this
- * <code>URLConnection</code>.
- *
- * @return java.util.jar.JarEntry the JarEntry referenced
- *
+ * Returns the JarEntry of the entry referenced by this {@code
+ * URLConnection}.
+ *
+ * @return the JarEntry referenced
+ *
* @throws IOException
* if an IO error occurs while getting the entry
*/
@@ -190,8 +197,8 @@
}
/**
- * Look up the JarEntry of the entry referenced by this
- * <code>URLConnection</code>.
+ * Look up the JarEntry of the entry referenced by this {@code
+ * URLConnection}.
*/
private void findJarEntry() throws IOException {
if (getEntryName() == null) {
@@ -213,15 +220,16 @@
*/
@Override
public InputStream getInputStream() throws IOException {
-
if (closed) {
- throw new IllegalStateException(Msg.getString("KA027"));
+ // KA027=Inputstream of the JarURLConnection has been closed
+ throw new IllegalStateException(Msg.getString("KA027")); //$NON-NLS-1$
}
connect();
if (jarInput != null) {
return jarInput;
}
if (jarEntry == null) {
+ // K00fc=Jar entry not specified
throw new IOException(Msg.getString("K00fc")); //$NON-NLS-1$
}
return jarInput = new JarURLConnectionInputStream(jarFile
@@ -229,11 +237,11 @@
}
/**
- * Returns the content type of the resource.
- * For jar file itself "x-java/jar" should be returned,
- * for jar entries the content type of the entry should be returned.
- * Returns non-null results ("content/unknown" for unknown types).
- *
+ * Returns the content type of the resource. For jar file itself
+ * "x-java/jar" should be returned, for jar entries the content type of the
+ * entry should be returned. Returns non-null results ("content/unknown" for
+ * unknown types).
+ *
* @return the content type
*/
@Override
@@ -241,31 +249,30 @@
if (url.getFile().endsWith("!/")) { //$NON-NLS-1$
// the type for jar file itself is always "x-java/jar"
return "x-java/jar"; //$NON-NLS-1$
- } else {
- String cType = null;
- String entryName = getEntryName();
-
- if (entryName != null) {
- // if there is an Jar Entry, get the content type from the name
- cType = guessContentTypeFromName(entryName);
- } else {
- try {
- connect();
- cType = jarFileURLConnection.getContentType();
- } catch (IOException ioe) {
- // Ignore
- }
- }
- if (cType == null) {
- cType = "content/unknown"; //$NON-NLS-1$
- }
- return cType;
}
+ String cType = null;
+ String entryName = getEntryName();
+
+ if (entryName != null) {
+ // if there is an Jar Entry, get the content type from the name
+ cType = guessContentTypeFromName(entryName);
+ } else {
+ try {
+ connect();
+ cType = jarFileURLConnection.getContentType();
+ } catch (IOException ioe) {
+ // Ignore
+ }
+ }
+ if (cType == null) {
+ cType = "content/unknown"; //$NON-NLS-1$
+ }
+ return cType;
}
/**
* Returns the content length of the resource. Test cases reveal that if the
- * URL is refering to a Jar file, this method returns a content-length
+ * URL is referring to a Jar file, this method answers a content-length
* returned by URLConnection. For jar entry it should return it's size.
* Otherwise, it will return -1.
*
@@ -277,26 +284,25 @@
connect();
if (jarEntry == null) {
return jarFileURLConnection.getContentLength();
- } else {
- return (int) getJarEntry().getSize();
}
+ return (int) getJarEntry().getSize();
} catch (IOException e) {
- //Ignored
+ // Ignored
}
return -1;
}
/**
- * Returns the object pointed by this <code>URL</code>. If this
- * URLConnection is pointing to a Jar File (no Jar Entry), this method will
- * return a <code>JarFile</code> If there is a Jar Entry, it will return
- * the object corresponding to the Jar entry content type.
- *
+ * Returns the object pointed by this {@code URL}. If this URLConnection is
+ * pointing to a Jar File (no Jar Entry), this method will return a {@code
+ * JarFile} If there is a Jar Entry, it will return the object corresponding
+ * to the Jar entry content type.
+ *
* @return a non-null object
*
* @throws IOException
- * if an IO error occured
- *
+ * if an IO error occurred
+ *
* @see ContentHandler
* @see ContentHandlerFactory
* @see java.io.IOException
@@ -354,9 +360,9 @@
*/
public static void closeCachedFiles() {
Set<Map.Entry<URL, JarFile>> s = jarCache.entrySet();
- synchronized(jarCache){
+ synchronized (jarCache) {
Iterator<Map.Entry<URL, JarFile>> i = s.iterator();
- while(i.hasNext()){
+ while (i.hasNext()) {
try {
ZipFile zip = i.next().getValue();
if (zip != null) {
@@ -366,7 +372,7 @@
// Ignored
}
}
- }
+ }
}
private class JarURLConnectionInputStream extends FilterInputStream {
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/util/ZoneInfo.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/util/ZoneInfo.java
index 110a0fd..01319e1 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/util/ZoneInfo.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/util/ZoneInfo.java
@@ -111,12 +111,23 @@
// Subtract the raw offset from all offsets so it can be changed
// and affect them too.
- // Find whether there exist any observances of DST.
-
for (int i = 0; i < mGmtOffs.length; i++) {
mGmtOffs[i] -= mRawOffset;
+ }
- if (mIsDsts[i] != 0) {
+ // Is this zone still observing DST?
+ // We don't care if they've historically used it: most places have at least once.
+ // We want to know whether the last "schedule info" (the unix times in the mTransitions
+ // array) is in the future. If it is, DST is still relevant.
+ // See http://code.google.com/p/android/issues/detail?id=877.
+ // This test means that for somewhere like Morocco, which tried DST in 2009 but has
+ // no future plans (and thus no future schedule info) will report "true" from
+ // useDaylightTime at the start of 2009 but "false" at the end. This seems appropriate.
+ long currentUnixTime = System.currentTimeMillis() / 1000;
+ if (mTransitions.length > 0) {
+ // (We're really dealing with uint32_t values, so long is most convenient in Java.)
+ long latestScheduleTime = mTransitions[mTransitions.length - 1] & 0xffffffff;
+ if (currentUnixTime < latestScheduleTime) {
mUseDst = true;
}
}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java b/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java
index ac0c877..7ae9de6 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainDatagramSocketImpl.java
@@ -154,7 +154,6 @@
close();
}
- @Override
public Object getOption(int optID) throws SocketException {
if (optID == SocketOptions.SO_TIMEOUT) {
return Integer.valueOf(receiveTimeout);
@@ -285,7 +284,6 @@
* @throws SocketException thrown if the option value is unsupported or
* invalid
*/
- @Override
public void setOption(int optID, Object val) throws SocketException {
/*
* for datagram sockets on some platforms we have to set both the
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/net/SocketInputStream.java b/libcore/luni/src/main/java/org/apache/harmony/luni/net/SocketInputStream.java
index 4b0b4b4..d19206d 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/net/SocketInputStream.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/net/SocketInputStream.java
@@ -78,7 +78,8 @@
}
if (0 > offset || offset >= buffer.length) {
- throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e"));//$NON-NLS-1$
+ // K002e=Offset out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset));//$NON-NLS-1$
}
if (0 > count || offset + count > buffer.length) {
throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f"));//$NON-NLS-1$
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java
index 7613f0e..bee1557 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java
@@ -108,10 +108,9 @@
// BEGIN android-deleted
// public long ttyAvailable() throws IOException;
+ // public long ttyRead(byte[] bytes, int offset, int length) throws IOException;
// END android-deleted
- public long ttyRead(byte[] bytes, int offset, int length) throws IOException;
-
// BEGIN android-added
public int ioctlAvailable(int fileDescriptor) throws IOException;
// END android-added
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java
index fb47f0d..3577451 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java
@@ -66,6 +66,11 @@
public int writeDirect(FileDescriptor fd, int address, int offset, int count)
throws IOException;
+ // BEGIN android-removed
+ // public int writev(FileDescriptor fd, Object[] buffers, int[] offsets,
+ // int[] counts, int length) throws IOException;
+ // END android-removed
+
public void setNonBlocking(FileDescriptor aFD, boolean block)
throws IOException;
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java
index 08bdac6..b7a62e2 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java
@@ -69,7 +69,7 @@
* Note that this value for Windows differs from the one for the
* page size (64K and 4K respectively).
*/
- public native int getAllocGranularity() throws IOException;
+ public native int getAllocGranularity();
public boolean lock(int fileDescriptor, long start, long length, int type,
boolean waitFlag) throws IOException {
@@ -79,160 +79,71 @@
return result != -1;
}
- private native int unlockImpl(int fileDescriptor, long start, long length);
+ // BEGIN android-changed
+ private native void unlockImpl(int fileDescriptor, long start, long length) throws IOException;
public void unlock(int fileDescriptor, long start, long length)
throws IOException {
// Validate arguments
validateLockArgs(IFileSystem.SHARED_LOCK_TYPE, start, length);
- int result = unlockImpl(fileDescriptor, start, length);
- if (result == -1) {
- throw new IOException();
- }
+ unlockImpl(fileDescriptor, start, length);
}
- private native int fflushImpl(int fd, boolean metadata);
-
- public void fflush(int fileDescriptor, boolean metadata)
- throws IOException {
- int result = fflushImpl(fileDescriptor, metadata);
- if (result == -1) {
- throw new IOException();
- }
- }
+ public native void fflush(int fileDescriptor, boolean metadata) throws IOException;
/*
* File position seeking.
*/
-
- private native long seekImpl(int fd, long offset, int whence);
-
- public long seek(int fileDescriptor, long offset, int whence)
- throws IOException {
- long pos = seekImpl(fileDescriptor, offset, whence);
- if (pos == -1) {
- throw new IOException();
- }
- return pos;
- }
+ public native long seek(int fd, long offset, int whence) throws IOException;
/*
* Direct read/write APIs work on addresses.
*/
- private native long readDirectImpl(int fileDescriptor, int address,
- int offset, int length);
+ public native long readDirect(int fileDescriptor, int address, int offset, int length);
- public long readDirect(int fileDescriptor, int address, int offset,
- int length) throws IOException {
- long bytesRead = readDirectImpl(fileDescriptor, address, offset, length);
- if (bytesRead < -1) {
- throw new IOException();
- }
- return bytesRead;
- }
-
- private native long writeDirectImpl(int fileDescriptor, int address,
- int offset, int length);
-
- public long writeDirect(int fileDescriptor, int address, int offset,
- int length) throws IOException {
- long bytesWritten = writeDirectImpl(fileDescriptor, address, offset,
- length);
- if (bytesWritten < 0) {
- throw new IOException();
- }
- return bytesWritten;
- }
+ public native long writeDirect(int fileDescriptor, int address, int offset, int length)
+ throws IOException;
/*
* Indirect read/writes work on byte[]'s
*/
private native long readImpl(int fileDescriptor, byte[] bytes, int offset,
- int length);
+ int length) throws IOException;
public long read(int fileDescriptor, byte[] bytes, int offset, int length)
throws IOException {
if (bytes == null) {
throw new NullPointerException();
}
- long bytesRead = readImpl(fileDescriptor, bytes, offset, length);
- if (bytesRead < -1) {
- /*
- * TODO: bytesRead is never less than -1 so this code
- * does nothing?
- * The native code throws an exception in only one case
- * so perhaps this should be 'bytesRead < 0' to handle
- * any other cases. But the other cases have been
- * ignored until now so fixing this could break things
- */
- throw new IOException();
- }
- return bytesRead;
+ return readImpl(fileDescriptor, bytes, offset, length);
}
private native long writeImpl(int fileDescriptor, byte[] bytes,
- int offset, int length);
+ int offset, int length) throws IOException;
public long write(int fileDescriptor, byte[] bytes, int offset, int length)
throws IOException {
- long bytesWritten = writeImpl(fileDescriptor, bytes, offset, length);
- if (bytesWritten < 0) {
- throw new IOException();
+ if (bytes == null) {
+ throw new NullPointerException();
}
- return bytesWritten;
+ return writeImpl(fileDescriptor, bytes, offset, length);
}
+ // END android-changed
/*
* Scatter/gather calls.
*/
- public long readv(int fileDescriptor, int[] addresses, int[] offsets,
- int[] lengths, int size) throws IOException {
- long bytesRead = readvImpl(fileDescriptor, addresses, offsets, lengths,
- size);
- if (bytesRead < -1) {
- throw new IOException();
- }
- return bytesRead;
- }
+ public native long readv(int fileDescriptor, int[] addresses,
+ int[] offsets, int[] lengths, int size) throws IOException;
- private native long readvImpl(int fileDescriptor, int[] addresses,
- int[] offsets, int[] lengths, int size);
+ public native long writev(int fileDescriptor, int[] addresses, int[] offsets,
+ int[] lengths, int size) throws IOException;
- public long writev(int fileDescriptor, int[] addresses, int[] offsets,
- int[] lengths, int size) throws IOException {
- long bytesWritten = writevImpl(fileDescriptor, addresses, offsets,
- lengths, size);
- if (bytesWritten < 0) {
- throw new IOException();
- }
- return bytesWritten;
- }
+ // BEGIN android-changed
+ public native void close(int fileDescriptor) throws IOException;
- private native long writevImpl(int fileDescriptor, int[] addresses,
- int[] offsets, int[] lengths, int size);
-
- private native int closeImpl(int fileDescriptor);
-
- /*
- * (non-Javadoc)
- *
- * @see org.apache.harmony.luni.platform.IFileSystem#close(long)
- */
- public void close(int fileDescriptor) throws IOException {
- int rc = closeImpl(fileDescriptor);
- if (rc == -1) {
- throw new IOException();
- }
- }
-
- public void truncate(int fileDescriptor, long size) throws IOException {
- int rc = truncateImpl(fileDescriptor, size);
- if (rc < 0) {
- throw new IOException();
- }
- }
-
- private native int truncateImpl(int fileDescriptor, long size);
+ public native void truncate(int fileDescriptor, long size) throws IOException;
+ // END android-changed
public int open(byte[] fileName, int mode) throws FileNotFoundException {
if (fileName == null) {
@@ -254,16 +165,10 @@
private native int openImpl(byte[] fileName, int mode);
- public long transfer(int fileHandler, FileDescriptor socketDescriptor,
- long offset, long count) throws IOException {
- long result = transferImpl(fileHandler, socketDescriptor, offset, count);
- if (result < 0)
- throw new IOException();
- return result;
- }
-
- private native long transferImpl(int fileHandler,
- FileDescriptor socketDescriptor, long offset, long count);
+ // BEGIN android-changed
+ public native long transfer(int fd, FileDescriptor sd, long offset, long count)
+ throws IOException;
+ // END android-changed
// BEGIN android-deleted
// public long ttyAvailable() throws IOException {
@@ -277,17 +182,15 @@
// private native long ttyAvailableImpl();
// END android-deleted
- public long ttyRead(byte[] bytes, int offset, int length) throws IOException {
- long nChar = ttyReadImpl(bytes, offset, length);
- // BEGIN android-changed
- if (nChar < -1) {
- throw new IOException();
- }
- // END android-changed
- return nChar;
- }
-
- private native long ttyReadImpl(byte[] bytes, int offset, int length);
+ // BEGIN android-deleted
+ // public long ttyRead(byte[] bytes, int offset, int length) throws IOException {
+ // if (bytes == null) {
+ // throw new NullPointerException();
+ // }
+ // return ttyReadImpl(bytes, offset, length);
+ // }
+ // private native long ttyReadImpl(byte[] bytes, int offset, int length) throws IOException;
+ // END android-deleted
// BEGIN android-added
public native int ioctlAvailable(int fileDescriptor) throws IOException;
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java
index 0061d2a..8d06b1c 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java
@@ -73,29 +73,33 @@
return singleton;
}
- /**
- * This class is not designed to be publicly instantiated.
- *
- * @see #getOSMemory()
+ /*
+ * Native method to determine whether the underlying platform is little
+ * endian.
+ *
+ * @return <code>true</code> if the platform is little endian or
+ * <code>false</code> if it is big endian.
*/
- private OSMemory() {
- super();
- }
-
- /**
- * Returns whether the byte order of this machine is little endian or not..
- *
- * @return <code>false</code> for Big Endian, and
- * <code>true</code. for Little Endian.
- */
- // BEGIN android-changed
- /*public*/
private static native boolean isLittleEndianImpl();
- // END android-changed
- public boolean isLittleEndian() {
- return isLittleEndianImpl();
- }
+ /**
+ * This class is not designed to be publicly instantiated.
+ *
+ * @see #getOSMemory()
+ */
+ private OSMemory() {
+ super();
+ }
+
+ /**
+ * Returns whether the byte order of this machine is little endian or not.
+ *
+ * @return <code>false</code> for Big Endian, and
+ * <code>true</code> for Little Endian.
+ */
+ public boolean isLittleEndian() {
+ return NATIVE_ORDER == Endianness.LITTLE_ENDIAN;
+ }
/**
* Returns the natural byte order for this machine.
@@ -128,16 +132,8 @@
* @return the address of the start of the memory block.
* @throws OutOfMemoryError
* if the request cannot be satisfied.
- */
- // BEGIN android-changed
- // public long malloc(long length) throws OutOfMemoryError
- // {
- // OSResourcesMonitor.ensurePhysicalMemoryCapacity();
- // return mallocNative(length);
- // }
- // private native long mallocNative(long length) throws OutOfMemoryError;
+ */
public native int malloc(int length) throws OutOfMemoryError;
- // END android-changed
/**
* Deallocates space for a memory block that was previously allocated by a
@@ -620,10 +616,8 @@
public int mmap(int fileDescriptor, long alignment, long size,
int mapMode) throws IOException {
+ // No need to check mmapImpl return as it throws IOException in error cases
int address = mmapImpl(fileDescriptor, alignment, size, mapMode);
- if (address == -1) {
- throw new IOException();
- }
return address;
}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
index bd6a609..a3eae58 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
@@ -829,4 +829,28 @@
static native int writeSocketDirectImpl(FileDescriptor fd, int address, int offset, int count)
throws IOException;
+
+ // BEGIN android-removed
+ // /**
+ // * Write given buffers to a socket. The given buffers is a Object array, the
+ // * element of array must be direct buffer or a byte array to be written.
+ // *
+ // * @param fd
+ // * the socket on which to write the bytes
+ // * @param buffers
+ // * the element of array must be direct buffer or a byte array to
+ // * be written
+ // * @param offsets
+ // * the index of the first byte to be write
+ // * @param counts
+ // * the maximum number of bytes to be written
+ // * @param length
+ // * the size of buffer array
+ // * @return the actual number of bytes written
+ // * @throws IOException
+ // * if there is an underlying socket problem
+ // */
+ // public native int writev(FileDescriptor fd, Object[] buffers,
+ // int[] offsets, int[] counts, int length) throws IOException;
+ // END android-removed
}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/PlatformAddress.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/PlatformAddress.java
index 43702b2..0149cac 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/PlatformAddress.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/PlatformAddress.java
@@ -21,14 +21,17 @@
package org.apache.harmony.luni.platform;
-
/**
* The platform address class is an unsafe virtualization of an OS memory block.
- *
*/
public class PlatformAddress implements ICommonDataTypes, Comparable {
/**
+ * This final field defines the sentinel for an unknown address value.
+ */
+ static final int UNKNOWN = -1;
+
+ /**
* This final field defines the size of an address on this platform.
*/
static final int SIZEOF = Platform.getMemorySystem().getPointerSize();
@@ -38,12 +41,17 @@
*/
public static final PlatformAddress NULL = new PlatformAddress(0, 0);
+ /**
+ * INVALID is the canonical address with an invalid value
+ * (i.e. a non-address).
+ */
+ public static final PlatformAddress INVALID =
+ new PlatformAddress(UNKNOWN, UNKNOWN);
+
public static final IMemorySpy memorySpy = new RuntimeMemorySpy();
static final IMemorySystem osMemory = Platform.getMemorySystem();
- static final long UNKNOWN = -1;
-
final int osaddr;
final long size;
@@ -65,7 +73,7 @@
memorySpy.autoFree(this);
}
- public PlatformAddress duplicate(){
+ public PlatformAddress duplicate() {
return PlatformAddressFactory.on(osaddr, size);
}
@@ -264,7 +272,7 @@
return "PlatformAddress[" + osaddr + "]"; //$NON-NLS-1$ //$NON-NLS-2$
}
- public final long getSize(){
+ public final long getSize() {
return size;
}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/PlatformAddressFactory.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/PlatformAddressFactory.java
index 9ac8064..3590604 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/PlatformAddressFactory.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/PlatformAddressFactory.java
@@ -103,7 +103,12 @@
return addr;
}
- public static PlatformAddress allocMap(int fd, long start, long size, int mode) throws IOException{
+ public static PlatformAddress allocMap(int fd, long start, long size, int mode) throws IOException {
+ if (size == 0) {
+ // if size is 0, call to mmap has incorrect behaviour on
+ // unix and windows, so return empty address
+ return mapOn(0, 0);
+ }
int osAddress = PlatformAddress.osMemory.mmap(fd, start, size, mode);
PlatformAddress newMemory = mapOn(osAddress, size);
PlatformAddress.memorySpy.alloc(newMemory);
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties b/libcore/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties
index 280a8f5..b6cbcef 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties
@@ -38,7 +38,7 @@
K0020=Unknown format
K002b=Unknown pattern character - '{0}'
K002c=Access denied {0}
-K002e=Offset out of bounds
+K002e=Offset out of bounds \: {0}
K002f=Arguments out of bounds
K0032=Address null or destination port out of range
K0033=Unknown socket type
@@ -326,3 +326,6 @@
KA028=Cannot set protocol version when stream in use
KA029=Can't find resource for bundle {0}, key {1}
KA030=Write end dead
+K0031=Length out of bounds \: {0}
+K0032=Source size {0} does not fit into destination
+K0033=Start index ({0}) is greater than end index ({1})
diff --git a/libcore/luni/src/main/native/cbigint.c b/libcore/luni/src/main/native/cbigint.c
index d327940..92b2992 100644
--- a/libcore/luni/src/main/native/cbigint.c
+++ b/libcore/luni/src/main/native/cbigint.c
@@ -253,6 +253,34 @@
}
}
+#ifndef HY_LITTLE_ENDIAN
+void simpleMultiplyAddHighPrecisionBigEndianFix(U_64 *arg1, IDATA length, U_64 arg2, U_32 *result) {
+ /* Assumes result can hold the product and arg2 only holds 32 bits
+ of information */
+ U_64 product;
+ IDATA index, resultIndex;
+
+ index = resultIndex = 0;
+ product = 0;
+
+ do {
+ product = HIGH_IN_U64(product) + result[halfAt(resultIndex)] + arg2 * LOW_U32_FROM_PTR(arg1 + index);
+ result[halfAt(resultIndex)] = LOW_U32_FROM_VAR(product);
+ ++resultIndex;
+ product = HIGH_IN_U64(product) + result[halfAt(resultIndex)] + arg2 * HIGH_U32_FROM_PTR(arg1 + index);
+ result[halfAt(resultIndex)] = LOW_U32_FROM_VAR(product);
+ ++resultIndex;
+ } while (++index < length);
+
+ result[halfAt(resultIndex)] += HIGH_U32_FROM_VAR(product);
+ if (result[halfAt(resultIndex)] < HIGH_U32_FROM_VAR(product)) {
+ /* must be careful with ++ operator and macro expansion */
+ ++resultIndex;
+ while (++result[halfAt(resultIndex)] == 0) ++resultIndex;
+ }
+}
+#endif
+
void
multiplyHighPrecision (U_64 * arg1, IDATA length1, U_64 * arg2, IDATA length2,
U_64 * result, IDATA length)
@@ -281,10 +309,11 @@
{
simpleMultiplyAddHighPrecision (arg1, length1, LOW_IN_U64 (arg2[count]),
resultIn32 + (++index));
- simpleMultiplyAddHighPrecision (arg1, length1,
- HIGH_IN_U64 (arg2[count]),
- resultIn32 + (++index));
-
+#ifdef HY_LITTLE_ENDIAN
+ simpleMultiplyAddHighPrecision(arg1, length1, HIGH_IN_U64(arg2[count]), resultIn32 + (++index));
+#else
+ simpleMultiplyAddHighPrecisionBigEndianFix(arg1, length1, HIGH_IN_U64(arg2[count]), resultIn32 + (++index));
+#endif
}
}
diff --git a/libcore/luni/src/main/native/fltconst.h b/libcore/luni/src/main/native/fltconst.h
index 03a97cd..940d5fc 100644
--- a/libcore/luni/src/main/native/fltconst.h
+++ b/libcore/luni/src/main/native/fltconst.h
@@ -140,16 +140,23 @@
#define SET_PINF_SNGL_PTR(fltptr) *U32P((fltptr)) = SINGLE_EXPONENT_MASK
#define SET_NINF_SNGL_PTR(fltptr) *U32P((fltptr)) = (SINGLE_EXPONENT_MASK | SINGLE_SIGN_MASK)
-/* on some platforms (HP720) we cannot reference an unaligned float. Build them by hand, one U_32 at a time. */
-#if defined(ATOMIC_FLOAT_ACCESS)
-#define PTR_DOUBLE_STORE(dstPtr, aDoublePtr) HIGH_U32_FROM_DBL_PTR(dstPtr) = HIGH_U32_FROM_DBL_PTR(aDoublePtr); LOW_U32_FROM_DBL_PTR(dstPtr) = LOW_U32_FROM_DBL_PTR(aDoublePtr)
-#define PTR_DOUBLE_VALUE(dstPtr, aDoublePtr) HIGH_U32_FROM_DBL_PTR(aDoublePtr) = HIGH_U32_FROM_DBL_PTR(dstPtr); LOW_U32_FROM_DBL_PTR(aDoublePtr) = LOW_U32_FROM_DBL_PTR(dstPtr)
+#if defined(HY_WORD64)
+ #define PTR_DOUBLE_VALUE(dstPtr, aDoublePtr) ((U64U32DBL *)(aDoublePtr))->u64val = ((U64U32DBL *)(dstPtr))->u64val
+ #define PTR_DOUBLE_STORE(dstPtr, aDoublePtr) ((U64U32DBL *)(dstPtr))->u64val = ((U64U32DBL *)(aDoublePtr))->u64val
+ #define STORE_LONG(dstPtr, hi, lo) ((U64U32DBL *)(dstPtr))->u64val = (((U_64)(hi)) << 32) | (lo)
#else
-#define PTR_DOUBLE_STORE(dstPtr, aDoublePtr) (*(dstPtr) = *(aDoublePtr))
-#define PTR_DOUBLE_VALUE(dstPtr, aDoublePtr) (*(aDoublePtr) = *(dstPtr))
-#endif
+ /* on some platforms (HP720) we cannot reference an unaligned float. Build them by hand, one U_32 at a time. */
+ #if defined(ATOMIC_FLOAT_ACCESS)
+ #define PTR_DOUBLE_STORE(dstPtr, aDoublePtr) HIGH_U32_FROM_DBL_PTR(dstPtr) = HIGH_U32_FROM_DBL_PTR(aDoublePtr); LOW_U32_FROM_DBL_PTR(dstPtr) = LOW_U32_FROM_DBL_PTR(aDoublePtr)
+ #define PTR_DOUBLE_VALUE(dstPtr, aDoublePtr) HIGH_U32_FROM_DBL_PTR(aDoublePtr) = HIGH_U32_FROM_DBL_PTR(dstPtr); LOW_U32_FROM_DBL_PTR(aDoublePtr) = LOW_U32_FROM_DBL_PTR(dstPtr)
+ #else
+ #define PTR_DOUBLE_STORE(dstPtr, aDoublePtr) (*(dstPtr) = *(aDoublePtr))
+ #define PTR_DOUBLE_VALUE(dstPtr, aDoublePtr) (*(aDoublePtr) = *(dstPtr))
+ #endif
-#define STORE_LONG(dstPtr, hi, lo) HIGH_U32_FROM_LONG64_PTR(dstPtr) = (hi); LOW_U32_FROM_LONG64_PTR(dstPtr) = (lo)
+ #define STORE_LONG(dstPtr, hi, lo) HIGH_U32_FROM_LONG64_PTR(dstPtr) = (hi); LOW_U32_FROM_LONG64_PTR(dstPtr) = (lo)
+#endif /* HY_WORD64 */
+
#define PTR_SINGLE_VALUE(dstPtr, aSinglePtr) (*U32P(aSinglePtr) = *U32P(dstPtr))
#define PTR_SINGLE_STORE(dstPtr, aSinglePtr) *((U_32 *)(dstPtr)) = (*U32P(aSinglePtr))
diff --git a/libcore/luni/src/main/native/java_net_InetAddress.cpp b/libcore/luni/src/main/native/java_net_InetAddress.cpp
index d7b4931..2af493c 100644
--- a/libcore/luni/src/main/native/java_net_InetAddress.cpp
+++ b/libcore/luni/src/main/native/java_net_InetAddress.cpp
@@ -24,12 +24,9 @@
#include <stdio.h>
#include <string.h>
-#include <assert.h>
#include <netdb.h>
#include <errno.h>
-#include <cutils/properties.h>
-#include <cutils/adb_networking.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
@@ -48,19 +45,6 @@
}
}
-static void throwNullPointerException(JNIEnv* env)
-{
- const char* className = "java/lang/NullPointerException";
-
- jclass exClass = env->FindClass(className);
-
- if (exClass == NULL) {
- LOGE("Unable to find class %s", className);
- } else {
- env->ThrowNew(exClass, NULL);
- }
-}
-
#if LOG_DNS
static void logIpString(struct addrinfo* ai, const char* name)
{
@@ -80,33 +64,6 @@
}
#endif
-static jobjectArray getAllByNameUsingAdb(JNIEnv* env, const char* name)
-{
- struct in_addr outaddr;
- jobjectArray addressArray = NULL;
- jbyteArray byteArray;
-
-#if 0
- LOGI("ADB networking: -gethostbyname err %d addr 0x%08x %u.%u.%u.%u",
- err, (unsigned int)outaddr.a.s_addr,
- outaddr.j[0],outaddr.j[1],
- outaddr.j[2],outaddr.j[3]);
-#endif
-
- if (adb_networking_gethostbyname(name, &outaddr) >= 0) {
- addressArray = env->NewObjectArray(1, byteArrayClass, NULL);
- byteArray = env->NewByteArray(4);
- if (addressArray && byteArray) {
- env->SetByteArrayRegion(byteArray, 0, 4, (jbyte*) &outaddr.s_addr);
- env->SetObjectArrayElement(addressArray, 1, byteArray);
- }
- } else {
- jniThrowException(env, "java/net/UnknownHostException", "adb error");
- }
-
- return addressArray;
-}
-
static jobjectArray getAllByNameUsingDns(JNIEnv* env, const char* name,
jboolean preferIPv4Stack)
{
@@ -208,28 +165,12 @@
jboolean preferIPv4Stack)
{
if (javaName == NULL) {
- throwNullPointerException(env);
+ jniThrowException(env, "java/lang/NullPointerException", NULL);
return NULL;
}
const char* name = env->GetStringUTFChars(javaName, NULL);
- jobjectArray out = NULL;
-
- char useAdbNetworkingProperty[PROPERTY_VALUE_MAX];
- char adbConnected[PROPERTY_VALUE_MAX];
- property_get("android.net.use-adb-networking",
- useAdbNetworkingProperty, "");
- property_get("adb.connected",
- adbConnected, "");
-
- // Any non-empty string value for use-adb-networking is considered "set"
- if ((strlen(useAdbNetworkingProperty) > 0)
- && (strlen(adbConnected) > 0) ) {
- out = getAllByNameUsingAdb(env, name);
- } else {
- out = getAllByNameUsingDns(env, name, preferIPv4Stack);
- }
-
+ jobjectArray out = getAllByNameUsingDns(env, name, preferIPv4Stack);
env->ReleaseStringUTFChars(javaName, name);
return out;
}
@@ -247,57 +188,44 @@
jbyteArray javaAddress)
{
if (javaAddress == NULL) {
- throwNullPointerException(env);
- return NULL;
- }
-
- size_t addrlen = env->GetArrayLength(javaAddress);
- jbyte* rawAddress = env->GetByteArrayElements(javaAddress, NULL);
- if (rawAddress == NULL) {
- throwNullPointerException(env);
+ jniThrowException(env, "java/lang/NullPointerException", NULL);
return NULL;
}
// Convert the raw address bytes into a socket address structure.
- int ret = 0;
struct sockaddr_storage ss;
- struct sockaddr_in *sin = (struct sockaddr_in *) &ss;
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss;
- size_t socklen;
memset(&ss, 0, sizeof(ss));
- switch (addrlen) {
- case 4:
- socklen = sizeof(struct sockaddr_in);
- sin->sin_family = AF_INET;
- memcpy(&sin->sin_addr.s_addr, rawAddress, addrlen);
- env->ReleaseByteArrayElements(javaAddress, rawAddress, JNI_ABORT);
- break;
- case 16:
- socklen = sizeof(struct sockaddr_in6);
- sin6->sin6_family = AF_INET6;
- memcpy(&sin6->sin6_addr.s6_addr, rawAddress, addrlen);
- env->ReleaseByteArrayElements(javaAddress, rawAddress, JNI_ABORT);
- break;
- default:
- // The caller already throws an exception in this case. Don't worry
- // about it here.
- env->ReleaseByteArrayElements(javaAddress, rawAddress, JNI_ABORT);
- return NULL;
+
+ size_t socklen;
+ const size_t addressLength = env->GetArrayLength(javaAddress);
+ if (addressLength == 4) {
+ struct sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(&ss);
+ sin->sin_family = AF_INET;
+ socklen = sizeof(struct sockaddr_in);
+ jbyte* dst = reinterpret_cast<jbyte*>(&sin->sin_addr.s_addr);
+ env->GetByteArrayRegion(javaAddress, 0, 4, dst);
+ } else if (addressLength == 16) {
+ struct sockaddr_in6 *sin6 = reinterpret_cast<sockaddr_in6*>(&ss);
+ sin6->sin6_family = AF_INET6;
+ socklen = sizeof(struct sockaddr_in6);
+ jbyte* dst = reinterpret_cast<jbyte*>(&sin6->sin6_addr.s6_addr);
+ env->GetByteArrayRegion(javaAddress, 0, 16, dst);
+ } else {
+ // The caller already throws an exception in this case. Don't worry
+ // about it here.
+ return NULL;
}
// Look up the host name from the IP address.
char name[NI_MAXHOST];
- if (ret == 0) {
- ret = getnameinfo((struct sockaddr *) &ss, socklen, name, sizeof(name),
- NULL, 0, NI_NAMEREQD);
+ int ret = getnameinfo(reinterpret_cast<sockaddr*>(&ss), socklen,
+ name, sizeof(name), NULL, 0, NI_NAMEREQD);
+ if (ret != 0) {
+ jniThrowException(env, "java/net/UnknownHostException", gai_strerror(ret));
+ return NULL;
}
- if (ret == 0) {
- return env->NewStringUTF(name);
- }
-
- jniThrowException(env, "java/net/UnknownHostException", gai_strerror(ret));
- return NULL;
+ return env->NewStringUTF(name);
}
/*
diff --git a/libcore/luni/src/main/native/java_net_NetworkInterface.c b/libcore/luni/src/main/native/java_net_NetworkInterface.c
deleted file mode 100644
index db6d503..0000000
--- a/libcore/luni/src/main/native/java_net_NetworkInterface.c
+++ /dev/null
@@ -1,845 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-
-#include "JNIHelp.h"
-#include "jni.h"
-#include "errno.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <sys/ioctl.h>
-
-//--------------------------------------------------------------------
-// TODO copied from OSNetworkSystem. Might get into a separate .h file
-/**
- * Throws an IOException with the given message.
- */
-static void throwSocketException(JNIEnv *env, const char *message) {
- jclass exClass = (*env)->FindClass(env, "java/net/SocketException");
-
- if(exClass == NULL) {
- LOGE("Unable to find class java/net/SocketException");
- } else {
- (*env)->ThrowNew(env, exClass, message);
- }
-}
-
-
-/**
- * Throws a NullPointerException.
- */
-static void throwNullPointerException(JNIEnv *env) {
- jclass exClass = (*env)->FindClass(env, "java/lang/NullPointerException");
-
- if(exClass == NULL) {
- LOGE("Unable to find class java/lang/NullPointerException");
- } else {
- (*env)->ThrowNew(env, exClass, NULL);
- }
-}
-
-/**
- * @name Socket Errors
- * Error codes for socket operations
- *
- * @internal SOCKERR* range from -200 to -299 avoid overlap
- */
-#define SOCKERR_BADSOCKET -200 /* generic error */
-#define SOCKERR_NOTINITIALIZED -201 /* socket library uninitialized */
-#define SOCKERR_BADAF -202 /* bad address family */
-#define SOCKERR_BADPROTO -203 /* bad protocol */
-#define SOCKERR_BADTYPE -204 /* bad type */
-#define SOCKERR_SYSTEMBUSY -205 /* system busy handling requests */
-#define SOCKERR_SYSTEMFULL -206 /* too many sockets */
-#define SOCKERR_NOTCONNECTED -207 /* socket is not connected */
-#define SOCKERR_INTERRUPTED -208 /* the call was cancelled */
-#define SOCKERR_TIMEOUT -209 /* the operation timed out */
-#define SOCKERR_CONNRESET -210 /* the connection was reset */
-#define SOCKERR_WOULDBLOCK -211 /* the socket is marked as nonblocking operation would block */
-#define SOCKERR_ADDRNOTAVAIL -212 /* address not available */
-#define SOCKERR_ADDRINUSE -213 /* address already in use */
-#define SOCKERR_NOTBOUND -214 /* the socket is not bound */
-#define SOCKERR_UNKNOWNSOCKET -215 /* resolution of fileDescriptor to socket failed */
-#define SOCKERR_INVALIDTIMEOUT -216 /* the specified timeout is invalid */
-#define SOCKERR_FDSETFULL -217 /* Unable to create an FDSET */
-#define SOCKERR_TIMEVALFULL -218 /* Unable to create a TIMEVAL */
-#define SOCKERR_REMSOCKSHUTDOWN -219 /* The remote socket has shutdown gracefully */
-#define SOCKERR_NOTLISTENING -220 /* listen() was not invoked prior to accept() */
-#define SOCKERR_NOTSTREAMSOCK -221 /* The socket does not support connection-oriented service */
-#define SOCKERR_ALREADYBOUND -222 /* The socket is already bound to an address */
-#define SOCKERR_NBWITHLINGER -223 /* The socket is marked non-blocking & SO_LINGER is non-zero */
-#define SOCKERR_ISCONNECTED -224 /* The socket is already connected */
-#define SOCKERR_NOBUFFERS -225 /* No buffer space is available */
-#define SOCKERR_HOSTNOTFOUND -226 /* Authoritative Answer Host not found */
-#define SOCKERR_NODATA -227 /* Valid name, no data record of requested type */
-#define SOCKERR_BOUNDORCONN -228 /* The socket has not been bound or is already connected */
-#define SOCKERR_OPNOTSUPP -229 /* The socket does not support the operation */
-#define SOCKERR_OPTUNSUPP -230 /* The socket option is not supported */
-#define SOCKERR_OPTARGSINVALID -231 /* The socket option arguments are invalid */
-#define SOCKERR_SOCKLEVELINVALID -232 /* The socket level is invalid */
-#define SOCKERR_TIMEOUTFAILURE -233
-#define SOCKERR_SOCKADDRALLOCFAIL -234 /* Unable to allocate the sockaddr structure */
-#define SOCKERR_FDSET_SIZEBAD -235 /* The calculated maximum size of the file descriptor set is bad */
-#define SOCKERR_UNKNOWNFLAG -236 /* The flag is unknown */
-#define SOCKERR_MSGSIZE -237 /* The datagram was too big to fit the specified buffer & was truncated. */
-#define SOCKERR_NORECOVERY -238 /* The operation failed with no recovery possible */
-#define SOCKERR_ARGSINVALID -239 /* The arguments are invalid */
-#define SOCKERR_BADDESC -240 /* The socket argument is not a valid file descriptor */
-#define SOCKERR_NOTSOCK -241 /* The socket argument is not a socket */
-#define SOCKERR_HOSTENTALLOCFAIL -242 /* Unable to allocate the hostent structure */
-#define SOCKERR_TIMEVALALLOCFAIL -243 /* Unable to allocate the timeval structure */
-#define SOCKERR_LINGERALLOCFAIL -244 /* Unable to allocate the linger structure */
-#define SOCKERR_IPMREQALLOCFAIL -245 /* Unable to allocate the ipmreq structure */
-#define SOCKERR_FDSETALLOCFAIL -246 /* Unable to allocate the fdset structure */
-#define SOCKERR_OPFAILED -247
-#define SOCKERR_VALUE_NULL -248 /* The value indexed was NULL */
-#define SOCKERR_CONNECTION_REFUSED -249 /* connection was refused */
-#define SOCKERR_ENETUNREACH -250 /* network is not reachable */
-#define SOCKERR_EACCES -251 /* permissions do not allow action on socket */
-
-/**
- * Answer the errorString corresponding to the errorNumber, if available.
- * This function will answer a default error string, if the errorNumber is not
- * recognized.
- *
- * This function will have to be reworked to handle internationalization properly, removing
- * the explicit strings.
- *
- * @param anErrorNum the error code to resolve to a human readable string
- *
- * @return a human readable error string
- */
-
-static char * netLookupErrorString(int anErrorNum) {
- switch(anErrorNum) {
- case SOCKERR_BADSOCKET:
- return "Bad socket";
- case SOCKERR_NOTINITIALIZED:
- return "Socket library uninitialized";
- case SOCKERR_BADAF:
- return "Bad address family";
- case SOCKERR_BADPROTO:
- return "Bad protocol";
- case SOCKERR_BADTYPE:
- return "Bad type";
- case SOCKERR_SYSTEMBUSY:
- return "System busy handling requests";
- case SOCKERR_SYSTEMFULL:
- return "Too many sockets allocated";
- case SOCKERR_NOTCONNECTED:
- return "Socket is not connected";
- case SOCKERR_INTERRUPTED:
- return "The call was cancelled";
- case SOCKERR_TIMEOUT:
- return "The operation timed out";
- case SOCKERR_CONNRESET:
- return "The connection was reset";
- case SOCKERR_WOULDBLOCK:
- return "The socket is marked as nonblocking operation would block";
- case SOCKERR_ADDRNOTAVAIL:
- return "The address is not available";
- case SOCKERR_ADDRINUSE:
- return "The address is already in use";
- case SOCKERR_NOTBOUND:
- return "The socket is not bound";
- case SOCKERR_UNKNOWNSOCKET:
- return "Resolution of the FileDescriptor to socket failed";
- case SOCKERR_INVALIDTIMEOUT:
- return "The specified timeout is invalid";
- case SOCKERR_FDSETFULL:
- return "Unable to create an FDSET";
- case SOCKERR_TIMEVALFULL:
- return "Unable to create a TIMEVAL";
- case SOCKERR_REMSOCKSHUTDOWN:
- return "The remote socket has shutdown gracefully";
- case SOCKERR_NOTLISTENING:
- return "Listen() was not invoked prior to accept()";
- case SOCKERR_NOTSTREAMSOCK:
- return "The socket does not support connection-oriented service";
- case SOCKERR_ALREADYBOUND:
- return "The socket is already bound to an address";
- case SOCKERR_NBWITHLINGER:
- return "The socket is marked non-blocking & SO_LINGER is non-zero";
- case SOCKERR_ISCONNECTED:
- return "The socket is already connected";
- case SOCKERR_NOBUFFERS:
- return "No buffer space is available";
- case SOCKERR_HOSTNOTFOUND:
- return "Authoritative Answer Host not found";
- case SOCKERR_NODATA:
- return "Valid name, no data record of requested type";
- case SOCKERR_BOUNDORCONN:
- return "The socket has not been bound or is already connected";
- case SOCKERR_OPNOTSUPP:
- return "The socket does not support the operation";
- case SOCKERR_OPTUNSUPP:
- return "The socket option is not supported";
- case SOCKERR_OPTARGSINVALID:
- return "The socket option arguments are invalid";
- case SOCKERR_SOCKLEVELINVALID:
- return "The socket level is invalid";
- case SOCKERR_TIMEOUTFAILURE:
- return "The timeout operation failed";
- case SOCKERR_SOCKADDRALLOCFAIL:
- return "Failed to allocate address structure";
- case SOCKERR_FDSET_SIZEBAD:
- return "The calculated maximum size of the file descriptor set is bad";
- case SOCKERR_UNKNOWNFLAG:
- return "The flag is unknown";
- case SOCKERR_MSGSIZE:
- return "The datagram was too big to fit the specified buffer, so truncated";
- case SOCKERR_NORECOVERY:
- return "The operation failed with no recovery possible";
- case SOCKERR_ARGSINVALID:
- return "The arguments are invalid";
- case SOCKERR_BADDESC:
- return "The socket argument is not a valid file descriptor";
- case SOCKERR_NOTSOCK:
- return "The socket argument is not a socket";
- case SOCKERR_HOSTENTALLOCFAIL:
- return "Unable to allocate the hostent structure";
- case SOCKERR_TIMEVALALLOCFAIL:
- return "Unable to allocate the timeval structure";
- case SOCKERR_LINGERALLOCFAIL:
- return "Unable to allocate the linger structure";
- case SOCKERR_IPMREQALLOCFAIL:
- return "Unable to allocate the ipmreq structure";
- case SOCKERR_FDSETALLOCFAIL:
- return "Unable to allocate the fdset structure";
- case SOCKERR_CONNECTION_REFUSED:
- return "Connection refused";
-
- default:
- return "unkown error";
- }
-}
-
-/**
- * Converts a native address structure to a 4-byte array. Throws a
- * NullPointerException or an IOException in case of error. This is
- * signaled by a return value of -1. The normal return value is 0.
- */
-static int structInToJavaAddress(
- JNIEnv *env, struct in_addr *address, jbyteArray java_address) {
-
- if(java_address == NULL) {
- throwNullPointerException(env);
- return -1;
- }
-
- if((*env)->GetArrayLength(env, java_address) != sizeof(address->s_addr)) {
- jniThrowIOException(env, errno);
- return -1;
- }
-
- jbyte *java_address_bytes;
-
- java_address_bytes = (*env)->GetByteArrayElements(env, java_address, NULL);
-
- memcpy(java_address_bytes, &(address->s_addr), sizeof(address->s_addr));
-
- (*env)->ReleaseByteArrayElements(env, java_address, java_address_bytes, 0);
-
- return 0;
-}
-
-static jobject structInToInetAddress(JNIEnv *env, struct in_addr *address) {
- jbyteArray bytes;
- int success;
-
- bytes = (*env)->NewByteArray(env, 4);
-
- if(bytes == NULL) {
- return NULL;
- }
-
- success = structInToJavaAddress(env, address, bytes);
-
- if(success < 0) {
- return NULL;
- }
-
- jclass iaddrclass = (*env)->FindClass(env, "java/net/InetAddress");
-
- if(iaddrclass == NULL) {
- LOGE("Can't find java/net/InetAddress");
- jniThrowException(env, "java/lang/ClassNotFoundException", "java.net.InetAddress");
- return NULL;
- }
-
- jmethodID iaddrgetbyaddress = (*env)->GetStaticMethodID(env, iaddrclass, "getByAddress", "([B)Ljava/net/InetAddress;");
-
- if(iaddrgetbyaddress == NULL) {
- LOGE("Can't find method InetAddress.getByAddress(byte[] val)");
- jniThrowException(env, "java/lang/NoSuchMethodError", "InetAddress.getByAddress(byte[] val)");
- return NULL;
- }
-
- return (*env)->CallStaticObjectMethod(env, iaddrclass, iaddrgetbyaddress, bytes);
-}
-//--------------------------------------------------------------------
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/* structure for returning either and IPV4 or IPV6 ip address */
-typedef struct ipAddress_struct {
- union {
- char bytes[sizeof(struct in_addr)];
- struct in_addr inAddr;
- } addr;
- unsigned int length;
- unsigned int scope;
-} ipAddress_struct;
-
-/* structure for returning network interface information */
-typedef struct NetworkInterface_struct {
- char *name;
- char *displayName;
- unsigned int numberAddresses;
- unsigned int index;
- struct ipAddress_struct *addresses;
-} NetworkInterface_struct;
-
-/* array of network interface structures */
-typedef struct NetworkInterfaceArray_struct {
- unsigned int length;
- struct NetworkInterface_struct *elements;
-} NetworkInterfaceArray_struct;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/**
- * Frees the memory allocated for the hyNetworkInterface_struct array passed in
- *
- * @param[in] portLibrary The port library.
- * @param[in] handle Pointer to array of network interface structures to be freed
- *
- * @return 0 on success
-*/
-int sock_free_network_interface_struct (struct NetworkInterfaceArray_struct *array) {
- unsigned int i = 0;
-
- if((array != NULL) && (array->elements != NULL)) {
-
- /* free the allocated memory in each of the structures */
- for(i = 0; i < array->length; i++) {
-
- /* free the name, displayName and addresses */
- if(array->elements[i].name != NULL) {
- free(array->elements[i].name);
- }
-
- if(array->elements[i].displayName != NULL) {
- free(array->elements[i].displayName);
- }
-
- if(array->elements[i].addresses != NULL) {
- free(array->elements[i].addresses);
- }
- }
-
- /* now free the array itself */
- free(array->elements);
- }
-
- return 0;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/**
- * Queries and returns the information for the network interfaces that are currently active within the system.
- * Applications are responsible for freeing the memory returned via the handle.
- *
- * @param[in] portLibrary The port library.
- * @param[in,out] array Pointer to structure with array of network interface entries
- * @param[in] boolean which indicates if we should prefer the IPv4 stack or not
- *
- * @return The number of elements in handle on success, negatvie portable error code on failure.
- -WSANO_RECOVERY if system calls required to get the info fail, -WSAENOBUFS if memory allocation fails
- * @note A return value of 0 indicates no interfaces exist
-*/
-int sockGetNetworkInterfaces(struct NetworkInterfaceArray_struct * array) {
-
- struct NetworkInterface_struct *interfaces = NULL;
- unsigned int nameLength = 0;
- unsigned int currentAdapterIndex = 0;
- unsigned int counter = 0;
- unsigned int result = 0;
- unsigned int numAddresses = 0;
- unsigned int currentIPAddressIndex = 0;
- unsigned int numAdapters = 0;
- int err = 0;
-
- struct ifconf ifc;
- int len = 32 * sizeof(struct ifreq);
- int socketP = 0;
- unsigned int totalInterfaces = 0;
- struct ifreq reqCopy;
- unsigned int counter2 = 0;
- char *lastName = NULL;
-
- int ifconfCommand = SIOCGIFCONF;
-
- /* this method is not guarranteed to return the IPV6 addresses. Code is include so that if the platform returns IPV6 addresses
- in reply to the SIOCGIFCONF they will be included. Howerver, it is not guarranteed or even expected that many platforms will
- include the IPV6 addresses. For this reason there are other specific implementations that will return the IPV6 addresses */
- /* first get the list of interfaces. We do not know how long the buffer needs to be so we try with one that allows for
- 32 interfaces. If this turns out not to be big enough then we expand the buffer to be able to support another
- 32 interfaces and try again. We do this until the result indicates that the result fit into the buffer provided */
- /* we need socket to do the ioctl so create one */
- socketP = socket(PF_INET, SOCK_DGRAM, 0);
- if(socketP < 0) {
- return socketP;
- }
- for(;;) {
- char *data = (char *)malloc(len * sizeof(char));
- if(data == NULL) {
- close(socketP);
- return SOCKERR_NOBUFFERS;
- }
- ifc.ifc_len = len;
- ifc.ifc_buf = data;
- errno = 0;
- if(ioctl(socketP, ifconfCommand, &ifc) != 0) {
- err = errno;
- free(ifc.ifc_buf);
- close(socketP);
- return SOCKERR_NORECOVERY;
- }
- if(ifc.ifc_len < len)
- break;
- /* the returned data was likely truncated, expand the buffer and try again */
- free(ifc.ifc_buf);
- len += 32 * sizeof(struct ifreq);
- }
-
- /* get the number of distinct interfaces */
- if(ifc.ifc_len != 0) {
- totalInterfaces = ifc.ifc_len / sizeof(struct ifreq);
- }
- lastName = NULL;
- for(counter = 0; counter < totalInterfaces; counter++) {
- if((NULL == lastName) || (strncmp(lastName, ifc.ifc_req[counter].ifr_name, IFNAMSIZ) != 0)) {
- /* make sure the interface is up */
- reqCopy = ifc.ifc_req[counter];
- ioctl(socketP, SIOCGIFFLAGS, &reqCopy);
- if((reqCopy.ifr_flags) & (IFF_UP == IFF_UP)) {
- numAdapters++;
- }
- }
- lastName = ifc.ifc_req[counter].ifr_name;
- }
-
- /* now allocate the space for the hyNetworkInterface structs and fill it in */
- interfaces = malloc(numAdapters * sizeof(NetworkInterface_struct));
- if(NULL == interfaces) {
- free(ifc.ifc_buf);
- close(socketP);
- return SOCKERR_NOBUFFERS;
- }
-
- /* initialize the structure so that we can free allocated if a failure occurs */
- for(counter = 0; counter < numAdapters; counter++) {
- interfaces[counter].name = NULL;
- interfaces[counter].displayName = NULL;
- interfaces[counter].addresses = NULL;
- }
-
- /* set up the return stucture */
- array->elements = interfaces;
- array->length = numAdapters;
- lastName = NULL;
- for(counter = 0; counter < totalInterfaces; counter++) {
- /* make sure the interface is still up */
- reqCopy = ifc.ifc_req[counter];
- ioctl(socketP, SIOCGIFFLAGS, &reqCopy);
- if((reqCopy.ifr_flags) & (IFF_UP == IFF_UP)) {
- /* since this function can return multiple entries for the same name, only do it for the first one with any given name */
- if((NULL == lastName) || (strncmp(lastName, ifc.ifc_req[counter].ifr_name, IFNAMSIZ) != 0)) {
-
- /* get the index for the interface */
- interfaces[currentAdapterIndex].index =
- ifc.ifc_req[counter].ifr_ifindex;
- /* get the name and display name for the adapter */
- /* there only seems to be one name so use it for both the name and the display name */
- nameLength = strlen(ifc.ifc_req[counter].ifr_name);
- interfaces[currentAdapterIndex].name = malloc(nameLength + 1);
-
- if(NULL == interfaces[currentAdapterIndex].name) {
- free(ifc.ifc_buf);
- sock_free_network_interface_struct(array);
- close(socketP);
- return SOCKERR_NOBUFFERS;
- }
- strncpy(interfaces[currentAdapterIndex].name, ifc.ifc_req[counter].ifr_name, nameLength);
- interfaces[currentAdapterIndex].name[nameLength] = 0;
- nameLength = strlen(ifc.ifc_req[counter].ifr_name);
- interfaces[currentAdapterIndex].displayName = malloc(nameLength + 1);
- if(NULL == interfaces[currentAdapterIndex].displayName) {
- free(ifc.ifc_buf);
- sock_free_network_interface_struct(array);
- close(socketP);
- return SOCKERR_NOBUFFERS;
- }
- strncpy(interfaces[currentAdapterIndex].displayName, ifc.ifc_req[counter].ifr_name, nameLength);
- interfaces[currentAdapterIndex].displayName[nameLength] = 0;
-
- /* check how many addresses/aliases this adapter has. aliases show up as adaptors with the same name */
- numAddresses = 0;
- for(counter2 = counter; counter2 < totalInterfaces; counter2++) {
- if(strncmp(ifc.ifc_req[counter].ifr_name, ifc.ifc_req[counter2].ifr_name, IFNAMSIZ) == 0) {
- if(ifc.ifc_req[counter2].ifr_addr.sa_family == AF_INET) {
- numAddresses++;
- }
- } else {
- break;
- }
- }
-
- /* allocate space for the addresses */
- interfaces[currentAdapterIndex].numberAddresses = numAddresses;
- interfaces[currentAdapterIndex].addresses = malloc(numAddresses * sizeof(ipAddress_struct));
- if(NULL == interfaces[currentAdapterIndex].addresses) {
- free(ifc.ifc_buf);
- sock_free_network_interface_struct(array);
- close(socketP);
- return SOCKERR_NOBUFFERS;
- }
-
- /* now get the addresses */
- currentIPAddressIndex = 0;
- lastName = ifc.ifc_req[counter].ifr_name;
-
- for(;;) {
- if(ifc.ifc_req[counter].ifr_addr.sa_family == AF_INET) {
- interfaces[currentAdapterIndex].addresses[currentIPAddressIndex].addr.inAddr.s_addr = ((struct sockaddr_in *) (&ifc.ifc_req[counter].ifr_addr))->sin_addr.s_addr;
- interfaces[currentAdapterIndex].addresses[currentIPAddressIndex].length = sizeof(struct in_addr);
- interfaces[currentAdapterIndex].addresses[currentIPAddressIndex].scope = 0;
- currentIPAddressIndex++;
- }
-
- /* we mean to increment the outside counter here as we want to skip the next entry as it is for the same interface
- as we are currently working on */
- if((counter + 1 < totalInterfaces) && (strncmp(ifc.ifc_req[counter + 1].ifr_name, lastName, IFNAMSIZ) == 0)) {
- counter++;
- } else {
- break;
- }
-
- }
- currentAdapterIndex++;
- }
- }
- } /* for over all interfaces */
- /* now an interface might have been taken down since we first counted them */
- array->length = currentAdapterIndex;
- /* free the memory now that we are done with it */
- free(ifc.ifc_buf);
- close(socketP);
-
- return 0;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/**
- * Answer an array of NetworkInterface objects. One for each network interface within the system
- *
- * @param env pointer to the JNI library
- * @param clazz the class of the object invoking the JNI function
- *
- * @return an array of NetworkInterface objects of length 0 or more
- */
-
-static jobjectArray getNetworkInterfacesImpl(JNIEnv * env, jclass clazz) {
-
- /* variables to store network interfac edata returned by call to port library */
- struct NetworkInterfaceArray_struct networkInterfaceArray;
- int result = 0;
-
- /* variables for class and method objects needed to create bridge to java */
- jclass networkInterfaceClass = NULL;
- jclass inetAddressClass = NULL;
- jclass utilClass = NULL;
- jmethodID methodID = NULL;
- jmethodID utilMid = NULL;
-
- /* JNI objects used to return values from native call */
- jstring name = NULL;
- jstring displayName = NULL;
- jobjectArray addresses = NULL;
- jobjectArray networkInterfaces = NULL;
- jbyteArray bytearray = NULL;
-
- /* jobjects used to build the object arrays returned */
- jobject currentInterface = NULL;
- jobject element = NULL;
-
- /* misc variables needed for looping and determining inetAddress info */
- unsigned int i = 0;
- unsigned int j = 0;
- unsigned int nameLength = 0;
-
- /* get the classes and methods that we need for later calls */
- networkInterfaceClass = (*env)->FindClass(env, "java/net/NetworkInterface");
- if(networkInterfaceClass == NULL) {
- throwSocketException(env, netLookupErrorString(SOCKERR_NORECOVERY));
- return NULL;
- }
-
- inetAddressClass = (*env)->FindClass(env, "java/net/InetAddress");
- if(inetAddressClass == NULL) {
- throwSocketException(env, netLookupErrorString(SOCKERR_NORECOVERY));
- return NULL;
- }
-
- methodID = (*env)->GetMethodID(env, networkInterfaceClass, "<init>",
- "(Ljava/lang/String;Ljava/lang/String;[Ljava/net/InetAddress;I)V");
- if(methodID == NULL) {
- throwSocketException(env, netLookupErrorString(SOCKERR_NORECOVERY));
- return NULL;
- }
-
- utilClass = (*env)->FindClass(env, "org/apache/harmony/luni/util/Util");
- if(!utilClass) {
- return NULL;
- }
-
- utilMid = ((*env)->GetStaticMethodID(env, utilClass, "toString",
- "([BII)Ljava/lang/String;"));
- if(!utilMid) {
- return NULL;
- }
-
- result = sockGetNetworkInterfaces(&networkInterfaceArray);
-
- if(result < 0) {
- /* this means an error occured. The value returned is the socket error that should be returned */
- throwSocketException(env, netLookupErrorString(result));
- return NULL;
- }
-
- /* now loop through the interfaces and extract the information to be returned */
- for(j = 0; j < networkInterfaceArray.length; j++) {
- /* set the name and display name and reset the addresses object array */
- addresses = NULL;
- name = NULL;
- displayName = NULL;
-
- if(networkInterfaceArray.elements[j].name != NULL) {
- nameLength = strlen(networkInterfaceArray.elements[j].name);
- bytearray = (*env)->NewByteArray(env, nameLength);
- if(bytearray == NULL) {
- /* NewByteArray should have thrown an exception */
- return NULL;
- }
- (*env)->SetByteArrayRegion(env, bytearray, (jint) 0, nameLength,
- (jbyte *)networkInterfaceArray.elements[j].name);
- name = (*env)->CallStaticObjectMethod(env, utilClass, utilMid,
- bytearray, (jint) 0, nameLength);
- if((*env)->ExceptionCheck(env)) {
- return NULL;
- }
- }
-
- if(networkInterfaceArray.elements[j].displayName != NULL) {
- nameLength = strlen(networkInterfaceArray.elements[j].displayName);
- bytearray = (*env)->NewByteArray(env, nameLength);
- if(bytearray == NULL) {
- /* NewByteArray should have thrown an exception */
- return NULL;
- }
- (*env)->SetByteArrayRegion(env, bytearray, (jint) 0, nameLength,
- (jbyte *)networkInterfaceArray.elements[j].displayName);
- displayName = (*env)->CallStaticObjectMethod(env, utilClass, utilMid,
- bytearray, (jint) 0, nameLength);
- if((*env)->ExceptionCheck(env)) {
- return NULL;
- }
- }
-
- /* generate the object with the inet addresses for the itnerface */
- for(i = 0; i < networkInterfaceArray.elements[j].numberAddresses; i++) {
- element = structInToInetAddress(env, (struct in_addr *) &(networkInterfaceArray.elements[j].addresses[i].addr.inAddr));
- if(i == 0) {
- addresses = (*env)->NewObjectArray(env,
- networkInterfaceArray.elements[j].numberAddresses,
- inetAddressClass, element);
- } else {
- (*env)->SetObjectArrayElement(env, addresses, i, element);
- }
- }
-
- /* now create the NetworkInterface object for this interface and then add it it ot the arrary that will be returned */
- currentInterface = (*env)->NewObject(env, networkInterfaceClass,
- methodID, name, displayName, addresses,
- networkInterfaceArray.elements[j].index);
-
- if(j == 0) {
- networkInterfaces = (*env)->NewObjectArray(env,
- networkInterfaceArray.length, networkInterfaceClass,
- currentInterface);
- } else {
- (*env)->SetObjectArrayElement(env, networkInterfaces, j, currentInterface);
- }
- }
-
- /* free the memory for the interfaces struct and return the new NetworkInterface List */
- sock_free_network_interface_struct(&networkInterfaceArray);
- return networkInterfaces;
-}
-
-
-/*
- * JNI registration
- */
-static JNINativeMethod gMethods[] = {
- /* name, signature, funcPtr */
- { "getNetworkInterfacesImpl", "()[Ljava/net/NetworkInterface;", getNetworkInterfacesImpl }
-};
-int register_java_net_NetworkInterface(JNIEnv* env) {
- return jniRegisterNativeMethods(env, "java/net/NetworkInterface",
- gMethods, NELEM(gMethods));
-
-}
diff --git a/libcore/luni/src/main/native/java_net_NetworkInterface.cpp b/libcore/luni/src/main/native/java_net_NetworkInterface.cpp
new file mode 100644
index 0000000..7d27056
--- /dev/null
+++ b/libcore/luni/src/main/native/java_net_NetworkInterface.cpp
@@ -0,0 +1,252 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+#include "AndroidSystemNatives.h"
+#include "JNIHelp.h"
+#include "jni.h"
+
+#include <errno.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+// A smart pointer that closes the given fd on going out of scope.
+// TODO: make this generally available.
+class scoped_fd {
+public:
+ explicit scoped_fd(int fd) : fd(fd) {
+ }
+
+ ~scoped_fd() {
+ close(fd);
+ }
+
+ int get() const {
+ return fd;
+ }
+
+private:
+ int fd;
+};
+
+// TODO: add a header file for shared utilities like this.
+extern jobject socketAddressToInetAddress(JNIEnv* env, sockaddr_storage* sockAddress);
+
+class NetworkInterfaceGetter {
+public:
+ NetworkInterfaceGetter() : interfaces(NULL) {
+ // Initialize this so we can be responsible for deleting it.
+ ifc.ifc_buf = NULL;
+ }
+
+ ~NetworkInterfaceGetter() {
+ delete[] ifc.ifc_buf;
+ }
+
+ jobjectArray getNetworkInterfaces(JNIEnv* env);
+
+private:
+ jobjectArray interfaces;
+ ifconf ifc;
+};
+
+// TODO: move to JNIHelp?
+static void jniThrowOutOfMemoryError(JNIEnv* env) {
+ jniThrowException(env, "java/lang/OutOfMemoryError", "native heap");
+}
+
+static void jniThrowSocketException(JNIEnv* env) {
+ jniThrowException(env, "java/net/SocketException", strerror(errno));
+}
+
+// Creates an InetAddress[] of size 'addressCount' from the ifc_req structs
+// starting at index 'startIndex' in 'ifc.ifc_req'.
+static jobjectArray MakeInetAddressArray(JNIEnv* env,
+ const ifconf& ifc, size_t startIndex, size_t addressCount) {
+ jclass inetAddressClass = env->FindClass("java/net/InetAddress");
+ if (inetAddressClass == NULL) {
+ return NULL;
+ }
+ jobjectArray addresses = env->NewObjectArray(addressCount, inetAddressClass, NULL);
+ if (addresses == NULL) {
+ return NULL;
+ }
+ for (size_t i = startIndex; i < startIndex + addressCount; ++i) {
+ sockaddr_storage* sockAddress =
+ reinterpret_cast<sockaddr_storage*>(&ifc.ifc_req[i].ifr_addr);
+ jobject element = socketAddressToInetAddress(env, sockAddress);
+ if (element == NULL) {
+ return NULL;
+ }
+ env->SetObjectArrayElement(addresses, i - startIndex, element);
+ if (env->ExceptionCheck()) {
+ return NULL;
+ }
+ }
+ return addresses;
+}
+
+// Creates a NetworkInterface with the given 'name', array of 'addresses',
+// and 'id'.
+static jobject MakeNetworkInterface(JNIEnv* env,
+ jstring name, jobjectArray addresses, jint id) {
+ jclass networkInterfaceClass = env->FindClass("java/net/NetworkInterface");
+ if (networkInterfaceClass == NULL) {
+ return NULL;
+ }
+ jmethodID networkInterfaceConstructor =
+ env->GetMethodID(networkInterfaceClass, "<init>",
+ "(Ljava/lang/String;Ljava/lang/String;[Ljava/net/InetAddress;I)V");
+ if (networkInterfaceConstructor == NULL) {
+ return NULL;
+ }
+ return env->NewObject(networkInterfaceClass, networkInterfaceConstructor,
+ name, name, addresses, id);
+}
+
+jobjectArray NetworkInterfaceGetter::getNetworkInterfaces(JNIEnv* env) {
+ scoped_fd fd(socket(PF_INET, SOCK_DGRAM, 0));
+ if (fd.get() < 0) {
+ jniThrowSocketException(env);
+ return NULL;
+ }
+
+ // Get the list of interfaces.
+ // Keep trying larger buffers until the result fits.
+ int len = 32 * sizeof(ifreq);
+ for (;;) {
+ // TODO: std::vector or boost::scoped_array would make this less awful.
+ if (ifc.ifc_buf != NULL) {
+ delete[] ifc.ifc_buf;
+ ifc.ifc_buf = NULL;
+ }
+ char* data = new char[len];
+ if (data == NULL) {
+ jniThrowOutOfMemoryError(env);
+ return NULL;
+ }
+ ifc.ifc_len = len;
+ ifc.ifc_buf = data;
+ if (ioctl(fd.get(), SIOCGIFCONF, &ifc) != 0) {
+ jniThrowSocketException(env);
+ return NULL;
+ }
+ if (ifc.ifc_len < len) {
+ break;
+ }
+ // The returned data was likely truncated.
+ // Expand the buffer and try again.
+ len += 32 * sizeof(ifreq);
+ }
+
+ // Count the number of distinct interfaces.
+ // Multiple addresses for a given interface have the same interface name.
+ // This whole function assumes that all an interface's addresses will be
+ // listed adjacent to one another.
+ size_t totalAddressCount = ifc.ifc_len / sizeof(ifreq);
+ size_t interfaceCount = 0;
+ const char* lastName = NULL;
+ for (size_t i = 0; i < totalAddressCount; ++i) {
+ const char* name = ifc.ifc_req[i].ifr_name;
+ if (lastName == NULL || strncmp(lastName, name, IFNAMSIZ) != 0) {
+ ++interfaceCount;
+ }
+ lastName = name;
+ }
+
+ // Build the NetworkInterface[]...
+ jclass networkInterfaceClass = env->FindClass("java/net/NetworkInterface");
+ if (networkInterfaceClass == NULL) {
+ return NULL;
+ }
+ interfaces = env->NewObjectArray(interfaceCount, networkInterfaceClass, NULL);
+ if (interfaces == NULL) {
+ return NULL;
+ }
+
+ // Fill in the NetworkInterface[].
+ size_t arrayIndex = 0;
+ for (size_t i = 0; i < totalAddressCount; ++i) {
+ // Get the index for this interface.
+ // (This is an id the kernel uses, unrelated to our array indexes.)
+ int id = ifc.ifc_req[i].ifr_ifindex;
+
+ // Get the name for this interface. There only seems to be one name so
+ // we use it for both name and the display name (as does the RI).
+ jstring name = env->NewStringUTF(ifc.ifc_req[i].ifr_name);
+ if (name == NULL) {
+ return NULL;
+ }
+
+ // Check how many addresses this interface has.
+ size_t addressCount = 0;
+ for (size_t j = i; j < totalAddressCount; ++j) {
+ if (strncmp(ifc.ifc_req[i].ifr_name, ifc.ifc_req[j].ifr_name, IFNAMSIZ) == 0) {
+ if (ifc.ifc_req[j].ifr_addr.sa_family == AF_INET) {
+ ++addressCount;
+ }
+ } else {
+ break;
+ }
+ }
+
+ // Get this interface's addresses as an InetAddress[].
+ jobjectArray addresses = MakeInetAddressArray(env, ifc, i, addressCount);
+ if (addresses == NULL) {
+ return NULL;
+ }
+ // Create the NetworkInterface object and add it to the NetworkInterface[].
+ jobject interface = MakeNetworkInterface(env, name, addresses, id);
+ if (interface == NULL) {
+ return NULL;
+ }
+ env->SetObjectArrayElement(interfaces, arrayIndex++, interface);
+ if (env->ExceptionCheck()) {
+ return NULL;
+ }
+
+ // Skip over this interface's addresses to the next *interface*.
+ i += addressCount - 1;
+ }
+ return interfaces;
+}
+
+/**
+ * Returns an array of zero or more NetworkInterface objects, one for each
+ * network interface.
+ */
+static jobjectArray getNetworkInterfacesImpl(JNIEnv* env, jclass) {
+ NetworkInterfaceGetter getter;
+ return getter.getNetworkInterfaces(env);
+}
+
+/*
+ * JNI registration
+ */
+static JNINativeMethod gMethods[] = {
+ /* name, signature, funcPtr */
+ { "getNetworkInterfacesImpl", "()[Ljava/net/NetworkInterface;", (void*) getNetworkInterfacesImpl },
+};
+int register_java_net_NetworkInterface(JNIEnv* env) {
+ return jniRegisterNativeMethods(env, "java/net/NetworkInterface",
+ gMethods, NELEM(gMethods));
+}
diff --git a/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSFileSystem.cpp b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSFileSystem.cpp
index 38f3d36..aaa10d3 100644
--- a/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSFileSystem.cpp
+++ b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSFileSystem.cpp
@@ -14,401 +14,305 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
+// BEGIN android-note
+// This file corresponds to harmony's OSFileSystem.c and OSFileSystemLinux32.c.
+// It has been greatly simplified by the assumption that the underlying
+// platform is always Linux.
+// END android-note
+
/*
* Common natives supporting the file system interface.
*/
#define HyMaxPath 1024
-#define HyOpenRead 1 /* Values for HyFileOpen */
+
+/* Values for HyFileOpen */
+#define HyOpenRead 1
#define HyOpenWrite 2
#define HyOpenCreate 4
#define HyOpenTruncate 8
#define HyOpenAppend 16
#define HyOpenText 32
-
/* Use this flag with HyOpenCreate, if this flag is specified then
- * trying to create an existing file will fail
+ * trying to create an existing file will fail
*/
#define HyOpenCreateNew 64
-#define HyOpenSync 128
+#define HyOpenSync 128
#define SHARED_LOCK_TYPE 1L
#include "JNIHelp.h"
#include "AndroidSystemNatives.h"
-#include <string.h>
-#include <stdio.h>
+#include <assert.h>
#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
#include <sys/sendfile.h>
#include <sys/uio.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-
-typedef struct socket_struct {
- int sock;
- unsigned short family;
-} socket_struct;
static void convertToPlatform(char *path) {
char *pathIndex;
pathIndex = path;
while (*pathIndex != '\0') {
- if(*pathIndex == '\\') {
+ if (*pathIndex == '\\') {
*pathIndex = '/';
}
pathIndex++;
}
}
-static int
-EsTranslateOpenFlags(int flags) {
+static int EsTranslateOpenFlags(int flags) {
int realFlags = 0;
- if(flags & HyOpenAppend) {
+ if (flags & HyOpenAppend) {
realFlags |= O_APPEND;
}
- if(flags & HyOpenTruncate) {
+ if (flags & HyOpenTruncate) {
realFlags |= O_TRUNC;
}
- if(flags & HyOpenCreate) {
+ if (flags & HyOpenCreate) {
realFlags |= O_CREAT;
}
- if(flags & HyOpenCreateNew) {
+ if (flags & HyOpenCreateNew) {
realFlags |= O_EXCL | O_CREAT;
}
#ifdef O_SYNC
- if(flags & HyOpenSync) {
- realFlags |= O_SYNC;
- }
-#endif
- if(flags & HyOpenRead) {
- if(flags & HyOpenWrite) {
+ if (flags & HyOpenSync) {
+ realFlags |= O_SYNC;
+ }
+#endif
+ if (flags & HyOpenRead) {
+ if (flags & HyOpenWrite) {
return (O_RDWR | realFlags);
}
return (O_RDONLY | realFlags);
}
- if(flags & HyOpenWrite) {
+ if (flags & HyOpenWrite) {
return (O_WRONLY | realFlags);
}
return -1;
}
-/**
- * Lock the file identified by the given handle.
- * The range and lock type are given.
- */
-static jint harmony_io_lockImpl(JNIEnv * env, jobject thiz, jint handle,
- jlong start, jlong length, jint typeFlag, jboolean waitFlag) {
+// Checks whether we can safely treat the given jlong as an off_t without
+// accidental loss of precision.
+// TODO: this is bogus; we should use _FILE_OFFSET_BITS=64.
+static bool offsetTooLarge(JNIEnv* env, jlong longOffset) {
+ if (sizeof(off_t) >= sizeof(jlong)) {
+ // We're only concerned about the possibility that off_t is
+ // smaller than jlong. off_t is signed, so we don't need to
+ // worry about signed/unsigned.
+ return false;
+ }
- int rc;
- int waitMode = (waitFlag) ? F_SETLKW : F_SETLK;
+ // TODO: use std::numeric_limits<off_t>::max() and min() when we have them.
+ assert(sizeof(off_t) == sizeof(int));
+ static const off_t off_t_max = INT_MAX;
+ static const off_t off_t_min = INT_MIN;
+
+ if (longOffset > off_t_max || longOffset < off_t_min) {
+ // "Value too large for defined data type".
+ jniThrowIOException(env, EOVERFLOW);
+ return true;
+ }
+ return false;
+}
+
+static jlong translateLockLength(jlong length) {
+ // FileChannel.tryLock uses Long.MAX_VALUE to mean "lock the whole
+ // file", where POSIX would use 0. We can support that special case,
+ // even for files whose actual length we can't represent. For other
+ // out of range lengths, though, we want our range checking to fire.
+ return (length == 0x7fffffffffffffffLL) ? 0 : length;
+}
+
+static struct flock flockFromStartAndLength(jlong start, jlong length) {
struct flock lock;
-
memset(&lock, 0, sizeof(lock));
- // If start or length overflow the max values we can represent, then max them out.
- if(start > 0x7fffffffL) {
- start = 0x7fffffffL;
- }
- if(length > 0x7fffffffL) {
- length = 0x7fffffffL;
- }
-
lock.l_whence = SEEK_SET;
lock.l_start = start;
lock.l_len = length;
- if((typeFlag & SHARED_LOCK_TYPE) == SHARED_LOCK_TYPE) {
+ return lock;
+}
+
+static jint harmony_io_lockImpl(JNIEnv* env, jobject, jint handle,
+ jlong start, jlong length, jint typeFlag, jboolean waitFlag) {
+
+ length = translateLockLength(length);
+ if (offsetTooLarge(env, start) || offsetTooLarge(env, length)) {
+ return -1;
+ }
+
+ struct flock lock(flockFromStartAndLength(start, length));
+
+ if ((typeFlag & SHARED_LOCK_TYPE) == SHARED_LOCK_TYPE) {
lock.l_type = F_RDLCK;
} else {
lock.l_type = F_WRLCK;
}
- do {
- rc = fcntl(handle, waitMode, &lock);
- } while ((rc < 0) && (errno == EINTR));
-
- return (rc == -1) ? -1 : 0;
+ int waitMode = (waitFlag) ? F_SETLKW : F_SETLK;
+ return TEMP_FAILURE_RETRY(fcntl(handle, waitMode, &lock));
}
-/**
- * Unlocks the specified region of the file.
- */
-static jint harmony_io_unlockImpl(JNIEnv * env, jobject thiz, jint handle,
+static void harmony_io_unlockImpl(JNIEnv* env, jobject, jint handle,
jlong start, jlong length) {
- int rc;
- struct flock lock;
-
- memset(&lock, 0, sizeof(lock));
-
- // If start or length overflow the max values we can represent, then max them out.
- if(start > 0x7fffffffL) {
- start = 0x7fffffffL;
- }
- if(length > 0x7fffffffL) {
- length = 0x7fffffffL;
+ length = translateLockLength(length);
+ if (offsetTooLarge(env, start) || offsetTooLarge(env, length)) {
+ return;
}
- lock.l_whence = SEEK_SET;
- lock.l_start = start;
- lock.l_len = length;
+ struct flock lock(flockFromStartAndLength(start, length));
lock.l_type = F_UNLCK;
- do {
- rc = fcntl(handle, F_SETLKW, &lock);
- } while ((rc < 0) && (errno == EINTR));
-
- return (rc == -1) ? -1 : 0;
+ int rc = TEMP_FAILURE_RETRY(fcntl(handle, F_SETLKW, &lock));
+ if (rc == -1) {
+ jniThrowIOException(env, errno);
+ }
}
/**
* Returns the granularity of the starting address for virtual memory allocation.
* (It's the same as the page size.)
- * Class: org_apache_harmony_luni_platform_OSFileSystem
- * Method: getAllocGranularity
- * Signature: ()I
*/
-static jint harmony_io_getAllocGranularity(JNIEnv * env, jobject thiz) {
- static int allocGranularity = 0;
- if(allocGranularity == 0) {
- allocGranularity = getpagesize();
- }
+static jint harmony_io_getAllocGranularity(JNIEnv* env, jobject) {
+ static int allocGranularity = getpagesize();
return allocGranularity;
}
-/*
- * Class: org_apache_harmony_luni_platform_OSFileSystem
- * Method: readvImpl
- * Signature: (I[J[I[I)J
- */
-static jlong harmony_io_readvImpl(JNIEnv *env, jobject thiz, jint fd,
- jintArray jbuffers, jintArray joffsets, jintArray jlengths, jint size) {
-
- jboolean bufsCopied = JNI_FALSE;
- jboolean offsetsCopied = JNI_FALSE;
- jboolean lengthsCopied = JNI_FALSE;
- jint *bufs;
- jint *offsets;
- jint *lengths;
- int i = 0;
- long totalRead = 0;
- struct iovec *vectors = (struct iovec *)malloc(size * sizeof(struct iovec));
- if(vectors == NULL) {
- return -1;
+// Translate three Java int[]s to a native iovec[] for readv and writev.
+static iovec* initIoVec(JNIEnv* env,
+ jintArray jBuffers, jintArray jOffsets, jintArray jLengths, jint size) {
+ iovec* vectors = new iovec[size];
+ if (vectors == NULL) {
+ jniThrowException(env, "java/lang/OutOfMemoryError", "native heap");
+ return NULL;
}
- bufs = env->GetIntArrayElements(jbuffers, &bufsCopied);
- offsets = env->GetIntArrayElements(joffsets, &offsetsCopied);
- lengths = env->GetIntArrayElements(jlengths, &lengthsCopied);
- while(i < size) {
- vectors[i].iov_base = (void *)((int)(bufs[i]+offsets[i]));
+ jint *buffers = env->GetIntArrayElements(jBuffers, NULL);
+ jint *offsets = env->GetIntArrayElements(jOffsets, NULL);
+ jint *lengths = env->GetIntArrayElements(jLengths, NULL);
+ for (int i = 0; i < size; ++i) {
+ vectors[i].iov_base = reinterpret_cast<void*>(buffers[i] + offsets[i]);
vectors[i].iov_len = lengths[i];
- i++;
}
- totalRead = readv(fd, vectors, size);
- if(bufsCopied) {
- env->ReleaseIntArrayElements(jbuffers, bufs, JNI_ABORT);
- }
- if(offsetsCopied) {
- env->ReleaseIntArrayElements(joffsets, offsets, JNI_ABORT);
- }
- if(lengthsCopied) {
- env->ReleaseIntArrayElements(jlengths, lengths, JNI_ABORT);
- }
- free(vectors);
- return totalRead;
+ env->ReleaseIntArrayElements(jBuffers, buffers, JNI_ABORT);
+ env->ReleaseIntArrayElements(jOffsets, offsets, JNI_ABORT);
+ env->ReleaseIntArrayElements(jLengths, lengths, JNI_ABORT);
+ return vectors;
}
-/*
- * Class: org_apache_harmony_luni_platform_OSFileSystem
- * Method: writevImpl
- * Signature: (I[J[I[I)J
- */
-static jlong harmony_io_writevImpl(JNIEnv *env, jobject thiz, jint fd,
- jintArray jbuffers, jintArray joffsets, jintArray jlengths, jint size) {
-
- jboolean bufsCopied = JNI_FALSE;
- jboolean offsetsCopied = JNI_FALSE;
- jboolean lengthsCopied = JNI_FALSE;
- jint *bufs;
- jint *offsets;
- jint *lengths;
- int i = 0;
- long totalRead = 0;
- struct iovec *vectors = (struct iovec *)malloc(size * sizeof(struct iovec));
- if(vectors == NULL) {
+static jlong harmony_io_readv(JNIEnv* env, jobject, jint fd,
+ jintArray jBuffers, jintArray jOffsets, jintArray jLengths, jint size) {
+ iovec* vectors = initIoVec(env, jBuffers, jOffsets, jLengths, size);
+ if (vectors == NULL) {
return -1;
}
- bufs = env->GetIntArrayElements(jbuffers, &bufsCopied);
- offsets = env->GetIntArrayElements(joffsets, &offsetsCopied);
- lengths = env->GetIntArrayElements(jlengths, &lengthsCopied);
- while(i < size) {
- vectors[i].iov_base = (void *)((int)(bufs[i]+offsets[i]));
- vectors[i].iov_len = lengths[i];
- i++;
+ long result = readv(fd, vectors, size);
+ if (result == -1) {
+ jniThrowIOException(env, errno);
}
- totalRead = writev(fd, vectors, size);
- if(bufsCopied) {
- env->ReleaseIntArrayElements(jbuffers, bufs, JNI_ABORT);
- }
- if(offsetsCopied) {
- env->ReleaseIntArrayElements(joffsets, offsets, JNI_ABORT);
- }
- if(lengthsCopied) {
- env->ReleaseIntArrayElements(jlengths, lengths, JNI_ABORT);
- }
- free(vectors);
- return totalRead;
+ delete[] vectors;
+ return result;
}
-/*
- * Class: org_apache_harmony_luni_platform_OSFileSystem
- * Method: transferImpl
- * Signature: (IJJ)J
- */
-static jlong harmony_io_transferImpl(JNIEnv *env, jobject thiz, jint fd,
- jobject sd, jlong offset, jlong count) {
+static jlong harmony_io_writev(JNIEnv* env, jobject, jint fd,
+ jintArray jBuffers, jintArray jOffsets, jintArray jLengths, jint size) {
+ iovec* vectors = initIoVec(env, jBuffers, jOffsets, jLengths, size);
+ if (vectors == NULL) {
+ return -1;
+ }
+ long result = writev(fd, vectors, size);
+ if (result == -1) {
+ jniThrowIOException(env, errno);
+ }
+ delete[] vectors;
+ return result;
+}
- int socket;
- off_t off;
+static jlong harmony_io_transfer(JNIEnv* env, jobject, jint fd, jobject sd,
+ jlong offset, jlong count) {
- socket = jniGetFDFromFileDescriptor(env, sd);
- if(socket == 0 || socket == -1) {
+ int socket = jniGetFDFromFileDescriptor(env, sd);
+ if (socket == -1) {
return -1;
}
/* Value of offset is checked in jint scope (checked in java layer)
The conversion here is to guarantee no value lost when converting offset to off_t
*/
- off = offset;
+ off_t off = offset;
- return sendfile(socket,(int)fd,(off_t *)&off,(size_t)count);
+ ssize_t rc = sendfile(socket, fd, &off, count);
+ if (rc == -1) {
+ jniThrowIOException(env, errno);
+ }
+ return rc;
}
-/*
- * Class: org_apache_harmony_io
- * Method: readDirectImpl
- * Signature: (IJI)J
- */
-static jlong harmony_io_readDirectImpl(JNIEnv * env, jobject thiz, jint fd,
+static jlong harmony_io_readDirect(JNIEnv* env, jobject, jint fd,
jint buf, jint offset, jint nbytes) {
- jint result;
- if(nbytes == 0) {
- return (jlong) 0;
+ if (nbytes == 0) {
+ return 0;
}
- result = read(fd, (void *) ((jint *)(buf+offset)), (int) nbytes);
- if(result == 0) {
- return (jlong) -1;
- } else {
- return (jlong) result;
+ jbyte* dst = reinterpret_cast<jbyte*>(buf + offset);
+ jlong rc = TEMP_FAILURE_RETRY(read(fd, dst, nbytes));
+ if (rc == 0) {
+ return -1;
}
+ if (rc == -1) {
+ jniThrowIOException(env, errno);
+ }
+ return rc;
}
-/*
- * Class: org_apache_harmony_io
- * Method: writeDirectImpl
- * Signature: (IJI)J
- */
-static jlong harmony_io_writeDirectImpl(JNIEnv * env, jobject thiz, jint fd,
+static jlong harmony_io_writeDirect(JNIEnv* env, jobject, jint fd,
jint buf, jint offset, jint nbytes) {
-
-
- int rc = 0;
-
- /* write will just do the right thing for HYPORT_TTY_OUT and HYPORT_TTY_ERR */
- rc = write (fd, (const void *) ((jint *)(buf+offset)), (int) nbytes);
-
- if(rc == -1) {
- jniThrowException(env, "java/io/IOException", strerror(errno));
- return -2;
+ jbyte* src = reinterpret_cast<jbyte*>(buf + offset);
+ jlong rc = TEMP_FAILURE_RETRY(write(fd, src, nbytes));
+ if (rc == -1) {
+ jniThrowIOException(env, errno);
}
- return (jlong) rc;
-
+ return rc;
}
-// BEGIN android-changed
-/*
- * Class: org_apache_harmony_io
- * Method: readImpl
- * Signature: (I[BII)J
- */
-static jlong harmony_io_readImpl(JNIEnv * env, jobject thiz, jint fd,
+static jlong harmony_io_readImpl(JNIEnv* env, jobject, jint fd,
jbyteArray byteArray, jint offset, jint nbytes) {
- jboolean isCopy;
- jbyte *bytes;
- jlong result;
-
if (nbytes == 0) {
return 0;
}
- bytes = env->GetByteArrayElements(byteArray, &isCopy);
-
- for (;;) {
- result = read(fd, (void *) (bytes + offset), (int) nbytes);
-
- if ((result != -1) || (errno != EINTR)) {
- break;
- }
-
- /*
- * If we didn't break above, that means that the read() call
- * returned due to EINTR. We shield Java code from this
- * possibility by trying again. Note that this is different
- * from EAGAIN, which should result in this code throwing
- * an InterruptedIOException.
- */
- }
-
+ jbyte* bytes = env->GetByteArrayElements(byteArray, NULL);
+ jlong rc = TEMP_FAILURE_RETRY(read(fd, bytes + offset, nbytes));
env->ReleaseByteArrayElements(byteArray, bytes, 0);
- if (result == 0) {
+ if (rc == 0) {
return -1;
}
-
- if (result == -1) {
+ if (rc == -1) {
if (errno == EAGAIN) {
jniThrowException(env, "java/io/InterruptedIOException",
"Read timed out");
} else {
- jniThrowException(env, "java/io/IOException", strerror(errno));
+ jniThrowIOException(env, errno);
}
}
-
- return result;
+ return rc;
}
-/*
- * Class: org_apache_harmony_io
- * Method: writeImpl
- * Signature: (I[BII)J
- */
-static jlong harmony_io_writeImpl(JNIEnv * env, jobject thiz, jint fd,
+static jlong harmony_io_writeImpl(JNIEnv* env, jobject, jint fd,
jbyteArray byteArray, jint offset, jint nbytes) {
- jboolean isCopy;
- jbyte *bytes = env->GetByteArrayElements(byteArray, &isCopy);
- jlong result;
-
- for (;;) {
- result = write(fd, (const char *) bytes + offset, (int) nbytes);
-
- if ((result != -1) || (errno != EINTR)) {
- break;
- }
-
- /*
- * If we didn't break above, that means that the read() call
- * returned due to EINTR. We shield Java code from this
- * possibility by trying again. Note that this is different
- * from EAGAIN, which should result in this code throwing
- * an InterruptedIOException.
- */
- }
-
+ jbyte* bytes = env->GetByteArrayElements(byteArray, NULL);
+ jlong result = TEMP_FAILURE_RETRY(write(fd, bytes + offset, nbytes));
env->ReleaseByteArrayElements(byteArray, bytes, JNI_ABORT);
if (result == -1) {
@@ -416,157 +320,77 @@
jniThrowException(env, "java/io/InterruptedIOException",
"Write timed out");
} else {
- jniThrowException(env, "java/io/IOException", strerror(errno));
+ jniThrowIOException(env, errno);
}
}
-
return result;
}
-// END android-changed
-/**
- * Seeks a file descriptor to a given file position.
- *
- * @param env pointer to Java environment
- * @param thiz pointer to object receiving the message
- * @param fd handle of file to be seeked
- * @param offset distance of movement in bytes relative to whence arg
- * @param whence enum value indicating from where the offset is relative
- * The valid values are defined in fsconstants.h.
- * @return the new file position from the beginning of the file, in bytes;
- * or -1 if a problem occurs.
- */
-static jlong harmony_io_seekImpl(JNIEnv * env, jobject thiz, jint fd,
- jlong offset, jint whence) {
-
- int mywhence = 0;
-
+static jlong harmony_io_seek(JNIEnv* env, jobject, jint fd, jlong offset,
+ jint javaWhence) {
/* Convert whence argument */
- switch (whence) {
- case 1:
- mywhence = 0;
- break;
- case 2:
- mywhence = 1;
- break;
- case 4:
- mywhence = 2;
- break;
- default:
- return -1;
- }
-
-
- off_t localOffset = (int) offset;
-
- if((mywhence < 0) || (mywhence > 2)) {
+ int nativeWhence = 0;
+ switch (javaWhence) {
+ case 1:
+ nativeWhence = SEEK_SET;
+ break;
+ case 2:
+ nativeWhence = SEEK_CUR;
+ break;
+ case 4:
+ nativeWhence = SEEK_END;
+ break;
+ default:
return -1;
}
- /* If file offsets are 32 bit, truncate the seek to that range */
- if(sizeof (off_t) < sizeof (jlong)) {
- if(offset > 0x7FFFFFFF) {
- localOffset = 0x7FFFFFFF;
- } else if(offset < -0x7FFFFFFF) {
- localOffset = -0x7FFFFFFF;
- }
+ // If the offset is relative, lseek(2) will tell us whether it's too large.
+ // We're just worried about too large an absolute offset, which would cause
+ // us to lie to lseek(2).
+ if (offsetTooLarge(env, offset)) {
+ return -1;
}
- return (jlong) lseek(fd, localOffset, mywhence);
-}
-
-/**
- * Flushes a file state to disk.
- *
- * @param env pointer to Java environment
- * @param thiz pointer to object receiving the message
- * @param fd handle of file to be flushed
- * @param metadata if true also flush metadata,
- * otherwise just flush data is possible.
- * @return zero on success and -1 on failure
- *
- * Method: fflushImpl
- * Signature: (IZ)I
- */
-static jint harmony_io_fflushImpl(JNIEnv * env, jobject thiz, jint fd,
- jboolean metadata) {
- return (jint) fsync(fd);
-}
-
-// BEGIN android-changed
-/**
- * Closes the given file handle
- *
- * @param env pointer to Java environment
- * @param thiz pointer to object receiving the message
- * @param fd handle of file to be closed
- * @return zero on success and -1 on failure
- *
- * Class: org_apache_harmony_io
- * Method: closeImpl
- * Signature: (I)I
- */
-static jint harmony_io_closeImpl(JNIEnv * env, jobject thiz, jint fd) {
- jint result;
-
- for (;;) {
- result = (jint) close(fd);
-
- if ((result != -1) || (errno != EINTR)) {
- break;
- }
-
- /*
- * If we didn't break above, that means that the close() call
- * returned due to EINTR. We shield Java code from this
- * possibility by trying again.
- */
+ jlong result = lseek(fd, offset, nativeWhence);
+ if (result == -1) {
+ jniThrowIOException(env, errno);
}
-
return result;
}
-// END android-changed
-
-/*
- * Class: org_apache_harmony_io
- * Method: truncateImpl
- * Signature: (IJ)I
- */
-static jint harmony_io_truncateImpl(JNIEnv * env, jobject thiz, jint fd,
- jlong size) {
-
- int rc;
- off_t length = (off_t) size;
-
- // If file offsets are 32 bit, truncate the newLength to that range
- if(sizeof (off_t) < sizeof (jlong)) {
- if(length > 0x7FFFFFFF) {
- length = 0x7FFFFFFF;
- } else if(length < -0x7FFFFFFF) {
- length = -0x7FFFFFFF;
- }
+// TODO: are we supposed to support the 'metadata' flag? (false => fdatasync.)
+static void harmony_io_fflush(JNIEnv* env, jobject, jint fd,
+ jboolean metadata) {
+ int rc = fsync(fd);
+ if (rc == -1) {
+ jniThrowIOException(env, errno);
}
-
- rc = ftruncate((int)fd, length);
-
- return (jint) rc;
-
}
-/*
- * Class: org_apache_harmony_io
- * Method: openImpl
- * Signature: ([BI)I
- */
-static jint harmony_io_openImpl(JNIEnv * env, jobject obj, jbyteArray path,
+static jint harmony_io_close(JNIEnv* env, jobject, jint fd) {
+ jint rc = TEMP_FAILURE_RETRY(close(fd));
+ if (rc == -1) {
+ jniThrowIOException(env, errno);
+ }
+ return rc;
+}
+
+static jint harmony_io_truncate(JNIEnv* env, jobject, jint fd, jlong length) {
+ if (offsetTooLarge(env, length)) {
+ return -1;
+ }
+
+ int rc = ftruncate(fd, length);
+ if (rc == -1) {
+ jniThrowIOException(env, errno);
+ }
+ return rc;
+}
+
+static jint harmony_io_openImpl(JNIEnv* env, jobject, jbyteArray path,
jint jflags) {
-
int flags = 0;
- int mode = 0;
- jint * portFD;
- jsize length;
- char pathCopy[HyMaxPath];
+ int mode = 0;
// BEGIN android-changed
// don't want default permissions to allow global access.
@@ -588,7 +412,7 @@
mode = 0600;
break;
case 256:
- flags = HyOpenWrite | HyOpenCreate | HyOpenAppend;
+ flags = HyOpenWrite | HyOpenCreate | HyOpenAppend;
mode = 0600;
break;
}
@@ -596,116 +420,56 @@
flags = EsTranslateOpenFlags(flags);
- length = env->GetArrayLength (path);
+ // TODO: clean this up when we clean up the java.io.File equivalent.
+ jsize length = env->GetArrayLength (path);
length = length < HyMaxPath - 1 ? length : HyMaxPath - 1;
+ char pathCopy[HyMaxPath];
env->GetByteArrayRegion (path, 0, length, (jbyte *)pathCopy);
pathCopy[length] = '\0';
convertToPlatform (pathCopy);
- int cc;
-
- if(pathCopy == NULL) {
- jniThrowException(env, "java/lang/NullPointerException", NULL);
- return -1;
- }
-
- do {
- cc = open(pathCopy, flags, mode);
- } while(cc < 0 && errno == EINTR);
-
- if(cc < 0 && errno > 0) {
+ jint cc = TEMP_FAILURE_RETRY(open(pathCopy, flags, mode));
+ // TODO: chase up the callers of this and check they wouldn't rather
+ // have us throw a meaningful IOException right here.
+ if (cc < 0 && errno > 0) {
cc = -errno;
}
-
return cc;
-
-
}
-// BEGIN android-deleted
-#if 0
-/*
- * Answers the number of remaining chars in the stdin.
- *
- * Class: org_apache_harmony_io
- * Method: ttyAvailableImpl
- * Signature: ()J
- */
-static jlong harmony_io_ttyAvailableImpl(JNIEnv *env, jobject thiz) {
-
- int rc;
- off_t curr, end;
-
- int avail = 0;
-
- // when redirected from a file
- curr = lseek(STDIN_FILENO, 0L, 2); /* don't use tell(), it doesn't exist on all platforms, i.e. linux */
- if(curr != -1) {
- end = lseek(STDIN_FILENO, 0L, 4);
- lseek(STDIN_FILENO, curr, 1);
- if(end >= curr) {
- return (jlong) (end - curr);
- }
- }
-
- /* ioctl doesn't work for files on all platforms (i.e. SOLARIS) */
-
- rc = ioctl (STDIN_FILENO, FIONREAD, &avail);
-
- /* 64 bit platforms use a 32 bit value, using IDATA fails on big endian */
- /* Pass in IDATA because ioctl() is device dependent, some devices may write 64 bits */
- if(rc != -1) {
- return (jlong) *(jint *) & avail;
- }
- return (jlong) 0;
-}
-#endif
-// END android-deleted
-
-// BEGIN android-added
-/*
- * Answers the number of remaining bytes in a file descriptor
- * using IOCTL.
- *
- * Class: org_apache_harmony_io
- * Method: ioctlAvailable
- * Signature: ()I
- */
-static jint harmony_io_ioctlAvailable(JNIEnv *env, jobject thiz, jint fd) {
- int avail = 0;
- int rc = ioctl(fd, FIONREAD, &avail);
-
+static jint harmony_io_ioctlAvailable(JNIEnv*env, jobject, jint fd) {
/*
* On underlying platforms Android cares about (read "Linux"),
* ioctl(fd, FIONREAD, &avail) is supposed to do the following:
- *
+ *
* If the fd refers to a regular file, avail is set to
* the difference between the file size and the current cursor.
* This may be negative if the cursor is past the end of the file.
- *
+ *
* If the fd refers to an open socket or the read end of a
* pipe, then avail will be set to a number of bytes that are
* available to be read without blocking.
- *
+ *
* If the fd refers to a special file/device that has some concept
* of buffering, then avail will be set in a corresponding way.
- *
+ *
* If the fd refers to a special device that does not have any
* concept of buffering, then the ioctl call will return a negative
* number, and errno will be set to ENOTTY.
- *
+ *
* If the fd refers to a special file masquerading as a regular file,
* then avail may be returned as negative, in that the special file
* may appear to have zero size and yet a previous read call may have
* actually read some amount of data and caused the cursor to be
* advanced.
*/
-
+ int avail = 0;
+ int rc = ioctl(fd, FIONREAD, &avail);
if (rc >= 0) {
/*
* Success, but make sure not to return a negative number (see
* above).
- */
+ */
if (avail < 0) {
avail = 0;
}
@@ -714,94 +478,37 @@
avail = 0;
} else {
/* Something strange is happening. */
- jniThrowException(env, "java/io/IOException", strerror(errno));
- avail = 0;
- }
+ jniThrowIOException(env, errno);
+ }
return (jint) avail;
}
-// END android-added
-
-/*
- * Reads the number of bytes from stdin.
- *
- * Class: org_apache_harmony_io
- * Method: ttyReadImpl
- * Signature: ([BII)J
- */
-static jlong harmony_io_ttyReadImpl(JNIEnv *env, jobject thiz,
- jbyteArray byteArray, jint offset, jint nbytes) {
-
- jboolean isCopy;
- jbyte *bytes = env->GetByteArrayElements(byteArray, &isCopy);
- jlong result;
-
- for(;;) {
-
- result = (jlong) read(STDIN_FILENO, (char *)(bytes + offset), (int) nbytes);
-
- if ((result != -1) || (errno != EINTR)) {
- break;
- }
-
- /*
- * If we didn't break above, that means that the read() call
- * returned due to EINTR. We shield Java code from this
- * possibility by trying again. Note that this is different
- * from EAGAIN, which should result in this code throwing
- * an InterruptedIOException.
- */
- }
-
- env->ReleaseByteArrayElements(byteArray, bytes, 0);
-
- if (result == 0) {
- return -1;
- }
-
- if (result == -1) {
- if (errno == EAGAIN) {
- jniThrowException(env, "java/io/InterruptedIOException",
- "Read timed out");
- } else {
- jniThrowException(env, "java/io/IOException", strerror(errno));
- }
- }
-
- return result;
-}
/*
* JNI registration
*/
static JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
- { "lockImpl", "(IJJIZ)I", (void*) harmony_io_lockImpl },
- { "getAllocGranularity","()I", (void*) harmony_io_getAllocGranularity },
- { "unlockImpl", "(IJJ)I", (void*) harmony_io_unlockImpl },
- { "fflushImpl", "(IZ)I", (void*) harmony_io_fflushImpl },
- { "seekImpl", "(IJI)J", (void*) harmony_io_seekImpl },
- { "readDirectImpl", "(IIII)J", (void*) harmony_io_readDirectImpl },
- { "writeDirectImpl", "(IIII)J", (void*) harmony_io_writeDirectImpl },
- { "readImpl", "(I[BII)J", (void*) harmony_io_readImpl },
- { "writeImpl", "(I[BII)J", (void*) harmony_io_writeImpl },
- { "readvImpl", "(I[I[I[II)J",(void*) harmony_io_readvImpl },
- { "writevImpl", "(I[I[I[II)J",(void*) harmony_io_writevImpl },
- { "closeImpl", "(I)I", (void*) harmony_io_closeImpl },
- { "truncateImpl", "(IJ)I", (void*) harmony_io_truncateImpl },
- { "openImpl", "([BI)I", (void*) harmony_io_openImpl },
- { "transferImpl", "(ILjava/io/FileDescriptor;JJ)J",
- (void*) harmony_io_transferImpl },
- // BEGIN android-deleted
- //{ "ttyAvailableImpl", "()J", (void*) harmony_io_ttyAvailableImpl },
- // END android-deleted
- // BEGIN android-added
+ { "close", "(I)V", (void*) harmony_io_close },
+ { "fflush", "(IZ)V", (void*) harmony_io_fflush },
+ { "getAllocGranularity","()I", (void*) harmony_io_getAllocGranularity },
{ "ioctlAvailable", "(I)I", (void*) harmony_io_ioctlAvailable },
- // END android added
- { "ttyReadImpl", "([BII)J", (void*) harmony_io_ttyReadImpl }
+ { "lockImpl", "(IJJIZ)I", (void*) harmony_io_lockImpl },
+ { "openImpl", "([BI)I", (void*) harmony_io_openImpl },
+ { "readDirect", "(IIII)J", (void*) harmony_io_readDirect },
+ { "readImpl", "(I[BII)J", (void*) harmony_io_readImpl },
+ { "readv", "(I[I[I[II)J",(void*) harmony_io_readv },
+ { "seek", "(IJI)J", (void*) harmony_io_seek },
+ { "transfer", "(ILjava/io/FileDescriptor;JJ)J",
+ (void*) harmony_io_transfer },
+ { "truncate", "(IJ)V", (void*) harmony_io_truncate },
+ { "unlockImpl", "(IJJ)V", (void*) harmony_io_unlockImpl },
+ { "writeDirect", "(IIII)J", (void*) harmony_io_writeDirect },
+ { "writeImpl", "(I[BII)J", (void*) harmony_io_writeImpl },
+ { "writev", "(I[I[I[II)J",(void*) harmony_io_writev },
};
-int register_org_apache_harmony_luni_platform_OSFileSystem(JNIEnv *_env) {
- return jniRegisterNativeMethods(_env,
- "org/apache/harmony/luni/platform/OSFileSystem", gMethods,
- NELEM(gMethods));
+int register_org_apache_harmony_luni_platform_OSFileSystem(JNIEnv* _env) {
+ return jniRegisterNativeMethods(_env,
+ "org/apache/harmony/luni/platform/OSFileSystem", gMethods,
+ NELEM(gMethods));
}
diff --git a/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSMemory.cpp b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSMemory.cpp
index 2e814cc..b1493f8 100644
--- a/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSMemory.cpp
+++ b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSMemory.cpp
@@ -144,9 +144,8 @@
*/
static void harmony_nio_getBytesImpl(JNIEnv *_env, jobject _this, jint pointer,
jbyteArray dst, jint offset, jint length) {
- jbyte *dst_ = (jbyte *)_env->GetPrimitiveArrayCritical(dst, (jboolean *)0);
- memcpy(dst_ + offset, (jbyte *)pointer, length);
- _env->ReleasePrimitiveArrayCritical(dst, dst_, 0);
+ jbyte* src = reinterpret_cast<jbyte*>(static_cast<uintptr_t>(pointer));
+ _env->SetByteArrayRegion(dst, offset, length, src);
}
/*
@@ -166,9 +165,8 @@
*/
static void harmony_nio_putBytesImpl(JNIEnv *_env, jobject _this,
jint pointer, jbyteArray src, jint offset, jint length) {
- jbyte *src_ = (jbyte *)_env->GetPrimitiveArrayCritical(src, (jboolean *)0);
- memcpy((jbyte *)pointer, src_ + offset, length);
- _env->ReleasePrimitiveArrayCritical(src, src_, JNI_ABORT);
+ jbyte* dst = reinterpret_cast<jbyte*>(static_cast<uintptr_t>(pointer));
+ _env->GetByteArrayRegion(src, offset, length, dst);
}
static void
diff --git a/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
index 635e1af..3dc4e21 100644
--- a/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
+++ b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
@@ -39,8 +39,6 @@
#include <sys/ioctl.h>
#include <sys/un.h>
-#include <cutils/properties.h>
-#include <cutils/adb_networking.h>
#include "AndroidSystemNatives.h"
// Temporary hack to build on systems that don't have up-to-date libc headers.
@@ -178,8 +176,6 @@
jclass byte_class;
jmethodID byte_class_init;
jfieldID byte_class_value;
- jclass string_class;
- jmethodID string_class_init;
jclass socketimpl_class;
jfieldID socketimpl_address;
jfieldID socketimpl_port;
@@ -189,16 +185,14 @@
jfieldID dpack_length;
} gCachedFields;
-static int useAdbNetworking = 0;
-
/* needed for connecting with timeout */
-typedef struct selectFDSet {
+struct selectFDSet {
int nfds;
int sock;
fd_set writeSet;
fd_set readSet;
fd_set exceptionSet;
-} selectFDSet;
+};
static const char * netLookupErrorString(int anErrorNum);
@@ -211,13 +205,6 @@
}
/**
- * Throws an IOException with the given message.
- */
-static void throwIOExceptionStr(JNIEnv *env, const char *message) {
- jniThrowException(env, "java/io/IOException", message);
-}
-
-/**
* Throws a NullPointerException.
*/
static void throwNullPointerException(JNIEnv *env) {
@@ -297,34 +284,19 @@
}
/**
- * Checks whether a 16-byte array represents an IPv4-mapped IPv6 address.
- *
- * @param addressBytes the address to check. Must be 16 bytes long.
- * @return true if address contains an IPv4-mapped address, false otherwise.
- */
-static bool isJavaMappedAddress(jbyte *addressBytes) {
- static const unsigned char mappedBytes[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff};
- return !memcmp(mappedBytes, addressBytes, sizeof(mappedBytes));
-}
-
-/**
* Converts a native address structure to an InetAddress object.
* Throws a NullPointerException or an IOException in case of
- * error. This is signaled by a return value of -1. The normal
- * return value is 0.
+ * error.
*
* @param sockaddress the sockaddr_storage structure to convert
*
* @return a jobject representing an InetAddress
*/
-static jobject socketAddressToInetAddress(JNIEnv *env,
- struct sockaddr_storage *sockaddress) {
-
- jbyteArray byteArray = socketAddressToByteArray(env, sockaddress);
- if (byteArray == NULL) // Exception has already been thrown.
+jobject socketAddressToInetAddress(JNIEnv* env, sockaddr_storage* sockAddress) {
+ jbyteArray byteArray = socketAddressToByteArray(env, sockAddress);
+ if (byteArray == NULL) {
return NULL;
-
+ }
return env->CallStaticObjectMethod(gCachedFields.iaddr_class,
gCachedFields.iaddr_getbyaddress, byteArray);
}
@@ -377,30 +349,30 @@
* @exception SocketError if the address family is unknown
*/
static int byteArrayToSocketAddress(JNIEnv *env,
- jbyteArray addressByteArray, int port, sockaddr_storage *sockaddress) {
- if (addressByteArray == NULL) {
- throwNullPointerException(env);
- return EFAULT;
+ jbyteArray addressBytes, int port, sockaddr_storage *sockaddress) {
+ if (addressBytes == NULL) {
+ throwNullPointerException(env);
+ return EFAULT;
}
- size_t addressLength = env->GetArrayLength(addressByteArray);
+ size_t addressLength = env->GetArrayLength(addressBytes);
// Convert the IP address bytes to the proper IP address type.
if (addressLength == 4) {
// IPv4 address.
- sockaddr_in *sin = (sockaddr_in *) sockaddress;
+ sockaddr_in *sin = reinterpret_cast<sockaddr_in*>(sockaddress);
memset(sin, 0, sizeof(sockaddr_in));
sin->sin_family = AF_INET;
sin->sin_port = htons(port);
- jbyte *rawBytes = (jbyte *) &sin->sin_addr.s_addr;
- env->GetByteArrayRegion(addressByteArray, 0, 4, rawBytes);
+ jbyte* dst = reinterpret_cast<jbyte*>(&sin->sin_addr.s_addr);
+ env->GetByteArrayRegion(addressBytes, 0, 4, dst);
} else if (addressLength == 16) {
// IPv6 address.
- sockaddr_in6 *sin6 = (sockaddr_in6 *) sockaddress;
+ sockaddr_in6 *sin6 = reinterpret_cast<sockaddr_in6*>(sockaddress);
memset(sin6, 0, sizeof(sockaddr_in6));
sin6->sin6_family = AF_INET6;
sin6->sin6_port = htons(port);
- jbyte *rawBytes = (jbyte *) &sin6->sin6_addr.s6_addr;
- env->GetByteArrayRegion(addressByteArray, 0, 16, rawBytes);
+ jbyte* dst = reinterpret_cast<jbyte*>(&sin6->sin6_addr.s6_addr);
+ env->GetByteArrayRegion(addressBytes, 0, 16, dst);
} else {
// Unknown address family.
throwSocketException(env, SOCKERR_BADAF);
@@ -419,20 +391,23 @@
* @param port the port number
* @param sockaddress the sockaddr_storage structure to write to
*
- * @return 0 on success, -1 on failure
+ * @return 0 on success, a system error code on failure
* @throw UnknownHostException if any error occurs
*
* @exception SocketError if the address family is unknown
*/
-static int inetAddressToSocketAddress(JNIEnv *env,
- jobject inetaddress, int port, sockaddr_storage *sockaddress) {
-
+static int inetAddressToSocketAddress(JNIEnv *env, jobject inetaddress,
+ int port, sockaddr_storage *sockaddress) {
// Get the byte array that stores the IP address bytes in the InetAddress.
- jbyteArray addressByteArray;
- addressByteArray = (jbyteArray)env->GetObjectField(inetaddress,
- gCachedFields.iaddr_ipaddress);
+ if (inetaddress == NULL) {
+ throwNullPointerException(env);
+ return EFAULT;
+ }
+ jbyteArray addressBytes =
+ reinterpret_cast<jbyteArray>(env->GetObjectField(inetaddress,
+ gCachedFields.iaddr_ipaddress));
- return byteArrayToSocketAddress(env, addressByteArray, port, sockaddress);
+ return byteArrayToSocketAddress(env, addressBytes, port, sockaddress);
}
/**
@@ -609,8 +584,7 @@
*
* @return the new Boolean
*/
-
-jobject newJavaLangBoolean(JNIEnv * env, jint anInt) {
+static jobject newJavaLangBoolean(JNIEnv * env, jint anInt) {
jclass tempClass;
jmethodID tempMethod;
@@ -627,8 +601,7 @@
*
* @return the new Byte
*/
-
-jobject newJavaLangByte(JNIEnv * env, jbyte val) {
+static jobject newJavaLangByte(JNIEnv * env, jbyte val) {
jclass tempClass;
jmethodID tempMethod;
@@ -645,8 +618,7 @@
*
* @return the new Integer
*/
-
-jobject newJavaLangInteger(JNIEnv * env, jint anInt) {
+static jobject newJavaLangInteger(JNIEnv * env, jint anInt) {
jclass tempClass;
jmethodID tempMethod;
@@ -655,22 +627,17 @@
return env->NewObject(tempClass, tempMethod, anInt);
}
-/**
- * Answer a new java.lang.String object.
- *
- * @param env pointer to the JNI library
- * @param anInt the byte[] constructor argument
- *
- * @return the new String
- */
+// Converts a number of milliseconds to a timeval.
+static timeval toTimeval(long ms) {
+ timeval tv;
+ tv.tv_sec = ms / 1000;
+ tv.tv_usec = (ms - tv.tv_sec*1000) * 1000;
+ return tv;
+}
-jobject newJavaLangString(JNIEnv * env, jbyteArray bytes) {
- jclass tempClass;
- jmethodID tempMethod;
-
- tempClass = gCachedFields.string_class;
- tempMethod = gCachedFields.string_class_init;
- return env->NewObject(tempClass, tempMethod, (jbyteArray) bytes);
+// Converts a timeval to a number of milliseconds.
+static long toMs(const timeval& tv) {
+ return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
/**
@@ -687,42 +654,10 @@
*/
static int time_msec_clock() {
- struct timeval tp;
+ timeval tp;
struct timezone tzp;
-
gettimeofday(&tp, &tzp);
- return (tp.tv_sec * 1000) + (tp.tv_usec / 1000);
-}
-
-/**
- * Check if the passed sockaddr_storage struct contains a localhost address
- *
- * @param address address pointer to the address to check
- *
- * @return 0 if the passed address isn't a localhost address
- */
-static int isLocalHost(struct sockaddr_storage *address) {
- if (address->ss_family == AF_INET) {
- struct sockaddr_in *sin = (struct sockaddr_in *) address;
- return (sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK));
- } else if (address->ss_family == AF_INET6) {
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) address;
- return IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr);
- } else {
- return 0;
- }
-}
-
-/**
- * Decide whether to use ADB networking for the given socket address.
- *
- * @param address pointer to sockaddr_storage structure to check
- *
- * @return true if ADB networking should be used, false otherwise.
- */
-static bool useAdbNetworkingForAddress(struct sockaddr_storage *address) {
- return useAdbNetworking && !isLocalHost(address) &&
- address->ss_family == AF_INET;
+ return toMs(tp);
}
/**
@@ -1059,54 +994,6 @@
}
/**
- * A helper method, to set the connect context to a Long object.
- *
- * @param env pointer to the JNI library
- * @param longclass Java Long Object
- */
-void setConnectContext(JNIEnv *env,jobject longclass,jbyte * context) {
- jclass descriptorCLS;
- jfieldID descriptorFID;
- descriptorCLS = env->FindClass("java/lang/Long");
- descriptorFID = env->GetFieldID(descriptorCLS, "value", "J");
- env->SetLongField(longclass, descriptorFID, (jlong)((jint)context));
-};
-
-/**
- * A helper method, to get the connect context.
- *
- * @param env pointer to the JNI library
- * @param longclass Java Long Object
- */
-jbyte *getConnectContext(JNIEnv *env, jobject longclass) {
- jclass descriptorCLS;
- jfieldID descriptorFID;
- descriptorCLS = env->FindClass("java/lang/Long");
- descriptorFID = env->GetFieldID(descriptorCLS, "value", "J");
- return (jbyte*) ((jint)env->GetLongField(longclass, descriptorFID));
-};
-
-// typical ip checksum
-unsigned short ip_checksum(unsigned short* buffer, int size) {
- register unsigned short * buf = buffer;
- register int bufleft = size;
- register unsigned long sum = 0;
-
- while (bufleft > 1) {
- sum = sum + (*buf++);
- bufleft = bufleft - sizeof(unsigned short );
- }
- if (bufleft) {
- sum = sum + (*(unsigned char*)buf);
- }
- sum = (sum >> 16) + (sum & 0xffff);
- sum += (sum >> 16);
-
- return (unsigned short )(~sum);
-}
-
-
-/**
* Wrapper for connect() that converts IPv4 addresses to IPv4-mapped IPv6
* addresses if necessary.
*
@@ -1180,42 +1067,28 @@
* @return 0, if no errors occurred, otherwise the (negative) error code.
*/
static int sockConnectWithTimeout(int handle, struct sockaddr_storage addr,
- unsigned int timeout, unsigned int step, jbyte *ctxt) {
+ int timeout, unsigned int step, jbyte *ctxt) {
int rc = 0;
- struct timeval passedTimeout;
int errorVal;
socklen_t errorValLen = sizeof(int);
- struct selectFDSet *context = NULL;
+ selectFDSet* context = reinterpret_cast<selectFDSet*>(ctxt);
if (SOCKET_STEP_START == step) {
-
- context = (struct selectFDSet *) ctxt;
-
context->sock = handle;
context->nfds = handle + 1;
- if (useAdbNetworkingForAddress(&addr)) {
-
- // LOGD("+connect to address 0x%08x (via adb)",
- // addr.sin_addr.s_addr);
- rc = adb_networking_connect_fd(handle, (struct sockaddr_in *) &addr);
- // LOGD("-connect ret %d errno %d (via adb)", rc, errno);
-
- } else {
- /* set the socket to non-blocking */
- int block = JNI_TRUE;
- rc = ioctl(handle, FIONBIO, &block);
- if (0 != rc) {
- return convertError(rc);
- }
-
- // LOGD("+connect to address 0x%08x (via normal) on handle %d",
- // addr.sin_addr.s_addr, handle);
- rc = doConnect(handle, &addr);
- // LOGD("-connect to address 0x%08x (via normal) returned %d",
- // addr.sin_addr.s_addr, (int) rc);
-
+ /* set the socket to non-blocking */
+ int block = JNI_TRUE;
+ rc = ioctl(handle, FIONBIO, &block);
+ if (rc != 0) {
+ return convertError(rc);
}
+
+ // LOGD("+connect to address 0x%08x (via normal) on handle %d",
+ // addr.sin_addr.s_addr, handle);
+ rc = doConnect(handle, &addr);
+ // LOGD("-connect to address 0x%08x (via normal) returned %d",
+ // addr.sin_addr.s_addr, (int) rc);
if (rc == -1) {
rc = errno;
@@ -1236,19 +1109,17 @@
} else if (SOCKET_STEP_CHECK == step) {
/* now check if we have connected yet */
- context = (struct selectFDSet *) ctxt;
-
/*
* set the timeout value to be used. Because on some unix platforms we
* don't get notified when a socket is closed we only sleep for 100ms
* at a time
+ *
+ * TODO: is this relevant for Android?
*/
- passedTimeout.tv_sec = 0;
if (timeout > 100) {
- passedTimeout.tv_usec = 100 * 1000;
- } else if ((int)timeout >= 0) {
- passedTimeout.tv_usec = timeout * 1000;
+ timeout = 100;
}
+ timeval passedTimeout(toTimeval(timeout));
/* initialize the FD sets for the select */
FD_ZERO(&(context->exceptionSet));
@@ -1262,7 +1133,7 @@
&(context->readSet),
&(context->writeSet),
&(context->exceptionSet),
- (int)timeout >= 0 ? &passedTimeout : NULL);
+ timeout >= 0 ? &passedTimeout : NULL);
/* if there is at least one descriptor ready to be checked */
if (0 < rc) {
@@ -1592,17 +1463,6 @@
jboolean jcl_supports_ipv6) {
// LOGD("ENTER oneTimeInitializationImpl of OSNetworkSystem");
- char useAdbNetworkingProperty[PROPERTY_VALUE_MAX];
- char adbConnectedProperty[PROPERTY_VALUE_MAX];
-
- property_get("android.net.use-adb-networking", useAdbNetworkingProperty, "");
- property_get("adb.connected", adbConnectedProperty, "");
-
- if (strlen((char *)useAdbNetworkingProperty) > 0
- && strlen((char *)adbConnectedProperty) > 0) {
- useAdbNetworking = 1;
- }
-
memset(&gCachedFields, 0, sizeof(gCachedFields));
struct CachedFields *c = &gCachedFields;
@@ -1616,7 +1476,6 @@
{&c->integer_class, "java/lang/Integer"},
{&c->boolean_class, "java/lang/Boolean"},
{&c->byte_class, "java/lang/Byte"},
- {&c->string_class, "java/lang/String"},
{&c->socketimpl_class, "java/net/SocketImpl"},
{&c->dpack_class, "java/net/DatagramPacket"}
};
@@ -1638,7 +1497,6 @@
{&c->integer_class_init, c->integer_class, "<init>", "(I)V", false},
{&c->boolean_class_init, c->boolean_class, "<init>", "(Z)V", false},
{&c->byte_class_init, c->byte_class, "<init>", "(B)V", false},
- {&c->string_class_init, c->string_class, "<init>", "([B)V", false},
{&c->iaddr_getbyaddress, c->iaddr_class, "getByAddress",
"([B)Ljava/net/InetAddress;", true}
};
@@ -1925,29 +1783,19 @@
jobject inetAddr, jint port, jint step, jbyteArray passContext) {
// LOGD("ENTER connectWithTimeoutSocketImpl");
- int handle;
- int result = 0;
- struct sockaddr_storage address;
- jbyte *context = NULL;
-
- result = inetAddressToSocketAddress(env, inetAddr, port, &address);
- if (result < 0)
+ sockaddr_storage address;
+ int result = inetAddressToSocketAddress(env, inetAddr, port, &address);
+ if (result < 0) {
return result;
-
- // Check if we're using adb networking and redirect in case it is used.
- if (useAdbNetworkingForAddress(&address)) {
- return osNetworkSystem_connectSocketImpl(env, clazz, fileDescriptor,
- trafficClass, inetAddr, port);
}
- handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
- if (handle == 0 || handle == -1) {
+ int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
+ if (handle == -1) {
throwSocketException(env, SOCKERR_BADDESC);
return -1;
}
- context = (jbyte *)env->GetPrimitiveArrayCritical(passContext, NULL);
-
+ jbyte* context = env->GetByteArrayElements(passContext, NULL);
switch (step) {
case SOCKET_CONNECT_STEP_START:
result = sockConnectWithTimeout(handle, address, 0,
@@ -1958,10 +1806,9 @@
SOCKET_STEP_CHECK, context);
break;
}
+ env->ReleaseByteArrayElements(passContext, context, 0);
- env->ReleasePrimitiveArrayCritical(passContext, context, JNI_ABORT);
-
- if (0 == result) {
+ if (result == 0) {
/* connected , so stop here */
sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, NULL);
} else if (result != SOCKERR_NOTCONNECTED) {
@@ -2009,16 +1856,6 @@
if (result < 0) // Exception has already been thrown.
return;
- // Check if we're using adb networking and redirect in case it is used.
- if (useAdbNetworkingForAddress(&address)) {
- int retVal = osNetworkSystem_connectSocketImpl(env, clazz,
- fileDescriptor, trafficClass, inetAddr, remotePort);
- if (retVal != 0) {
- throwSocketException(env, SOCKERR_BADSOCKET);
- }
- return;
- }
-
/*
* we will be looping checking for when we are connected so allocate
* the descriptor sets that we will use
@@ -2145,26 +1982,17 @@
return -1;
}
- if (useAdbNetworkingForAddress(&address)) {
-
- // LOGD("+connect to address 0x%08x port %d (via adb)",
- // address.sin_addr.s_addr, (int) port);
- ret = adb_networking_connect_fd(handle, (struct sockaddr_in *) &address);
- // LOGD("-connect ret %d errno %d (via adb)", ret, errno);
-
+ // call this method with a timeout of zero
+ osNetworkSystem_connectStreamWithTimeoutSocketImpl(env, clazz,
+ fileDescriptor, port, 0, trafficClass, inetAddr);
+ if (env->ExceptionOccurred() != 0) {
+ return -1;
} else {
-
- // call this method with a timeout of zero
- osNetworkSystem_connectStreamWithTimeoutSocketImpl(env, clazz,
- fileDescriptor, port, 0, trafficClass, inetAddr);
- if (env->ExceptionOccurred() != 0) {
- return -1;
- } else {
- return 0;
- }
-
+ return 0;
}
-
+
+ // TODO: unreachable code!
+
if (ret < 0) {
jniThrowException(env, "java/net/ConnectException",
netLookupErrorString(convertError(errno)));
@@ -2687,13 +2515,10 @@
int spaceAvailable = env->GetArrayLength(data) - offset;
int localCount = count < spaceAvailable? count : spaceAvailable;
- jboolean isCopy;
- jbyte *body = env->GetByteArrayElements(data, &isCopy);
+ jbyte* body = env->GetByteArrayElements(data, NULL);
// set timeout
- struct timeval tv;
- tv.tv_sec = timeout / 1000;
- tv.tv_usec = (timeout % 1000) * 1000;
+ timeval tv(toTimeval(timeout));
setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv,
sizeof(struct timeval));
@@ -2731,8 +2556,7 @@
int handle = 0;
int result = 0, sent = 0;
- jboolean isCopy;
- jbyte *message = env->GetByteArrayElements(data, &isCopy);
+ jbyte *message = env->GetByteArrayElements(data, NULL);
// Cap write length to available buf size
int spaceAvailable = env->GetArrayLength(data) - offset;
@@ -2878,111 +2702,87 @@
return sent;
}
+static bool initFdSet(JNIEnv* env, jobjectArray fdArray, jint count, fd_set* fdSet, int* maxFd) {
+ for (int i = 0; i < count; ++i) {
+ jobject fileDescriptor = env->GetObjectArrayElement(fdArray, i);
+ if (fileDescriptor == NULL) {
+ return false;
+ }
+
+ const int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
+ if (fd < 0 || fd > 1024) {
+ LOGE("selectImpl: invalid fd %i", fd);
+ continue;
+ }
+
+ FD_SET(fd, fdSet);
+
+ if (fd > *maxFd) {
+ *maxFd = fd;
+ }
+ }
+ return true;
+}
+
+static bool translateFdSet(JNIEnv* env, jobjectArray fdArray, jint count, const fd_set& fdSet, jint* flagArray, size_t offset, jint op) {
+ for (int i = 0; i < count; ++i) {
+ jobject fileDescriptor = env->GetObjectArrayElement(fdArray, i);
+ if (fileDescriptor == NULL) {
+ return false;
+ }
+
+ const int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
+ const bool valid = fd >= 0 && fd < 1024;
+
+ if (valid && FD_ISSET(fd, &fdSet)) {
+ flagArray[i + offset] = op;
+ } else {
+ flagArray[i + offset] = SOCKET_OP_NONE;
+ }
+ }
+ return true;
+}
+
static jint osNetworkSystem_selectImpl(JNIEnv* env, jclass clazz,
jobjectArray readFDArray, jobjectArray writeFDArray, jint countReadC,
- jint countWriteC, jintArray outFlags, jlong timeout) {
+ jint countWriteC, jintArray outFlags, jlong timeoutMs) {
// LOGD("ENTER selectImpl");
-
- struct timeval timeP;
- int result = 0;
- int size = 0;
- jobject gotFD;
- fd_set *fdset_read,*fdset_write;
- int handle;
- jboolean isCopy ;
- jint *flagArray;
- int val;
- unsigned int time_sec = (unsigned int)timeout/1000;
- unsigned int time_msec = (unsigned int)(timeout%1000);
-
- fdset_read = (fd_set *)malloc(sizeof(fd_set));
- fdset_write = (fd_set *)malloc(sizeof(fd_set));
-
- FD_ZERO(fdset_read);
- FD_ZERO(fdset_write);
-
- for (val = 0; val<countReadC; val++) {
-
- gotFD = env->GetObjectArrayElement(readFDArray,val);
-
- handle = jniGetFDFromFileDescriptor(env, gotFD);
-
- FD_SET(handle, fdset_read);
-
- if (0 > (size - handle)) {
- size = handle;
- }
+
+ // Initialize the fd_sets.
+ int maxFd = -1;
+ fd_set readFds;
+ fd_set writeFds;
+ FD_ZERO(&readFds);
+ FD_ZERO(&writeFds);
+ bool initialized = initFdSet(env, readFDArray, countReadC, &readFds, &maxFd) &&
+ initFdSet(env, writeFDArray, countWriteC, &writeFds, &maxFd);
+ if (!initialized) {
+ return -1;
}
-
- for (val = 0; val<countWriteC; val++) {
-
- gotFD = env->GetObjectArrayElement(writeFDArray,val);
-
- handle = jniGetFDFromFileDescriptor(env, gotFD);
-
- FD_SET(handle, fdset_write);
-
- if (0 > (size - handle)) {
- size = handle;
- }
+
+ // Initialize the timeout, if any.
+ timeval tv;
+ timeval* tvp = NULL;
+ if (timeoutMs >= 0) {
+ tv = toTimeval(timeoutMs);
+ tvp = &tv;
}
-
- /* the size is the max_fd + 1 */
- size =size + 1;
-
- if (0 > size) {
- result = SOCKERR_FDSET_SIZEBAD;
- } else {
- /* only set when timeout >= 0 (non-block)*/
- if (0 <= timeout) {
-
- timeP.tv_sec = time_sec;
- timeP.tv_usec = time_msec*1000;
-
- result = sockSelect(size, fdset_read, fdset_write, NULL, &timeP);
-
- } else {
- result = sockSelect(size, fdset_read, fdset_write, NULL, NULL);
- }
+
+ // Perform the select.
+ int result = sockSelect(maxFd + 1, &readFds, &writeFds, NULL, tvp);
+ if (result < 0) {
+ return result;
}
-
- if (0 < result) {
- /*output the result to a int array*/
- flagArray = env->GetIntArrayElements(outFlags, &isCopy);
-
- for (val=0; val<countReadC; val++) {
- gotFD = env->GetObjectArrayElement(readFDArray,val);
-
- handle = jniGetFDFromFileDescriptor(env, gotFD);
-
- if (FD_ISSET(handle,fdset_read)) {
- flagArray[val] = SOCKET_OP_READ;
- } else {
- flagArray[val] = SOCKET_OP_NONE;
- }
- }
-
- for (val=0; val<countWriteC; val++) {
-
- gotFD = env->GetObjectArrayElement(writeFDArray,val);
-
- handle = jniGetFDFromFileDescriptor(env, gotFD);
-
- if (FD_ISSET(handle,fdset_write)) {
- flagArray[val+countReadC] = SOCKET_OP_WRITE;
- } else {
- flagArray[val+countReadC] = SOCKET_OP_NONE;
- }
- }
-
- env->ReleaseIntArrayElements(outFlags, flagArray, 0);
+
+ // Translate the result into the int[] we're supposed to fill in.
+ jint* flagArray = env->GetIntArrayElements(outFlags, NULL);
+ if (flagArray == NULL) {
+ return -1;
}
-
- free(fdset_write);
- free(fdset_read);
-
- /* return both correct and error result, let java handle the exception*/
- return result;
+ bool okay = translateFdSet(env, readFDArray, countReadC, readFds, flagArray, 0, SOCKET_OP_READ) &&
+ translateFdSet(env, writeFDArray, countWriteC, writeFds, flagArray, countReadC, SOCKET_OP_WRITE);
+ env->ReleaseIntArrayElements(outFlags, flagArray, 0);
+ return okay ? 0 : -1;
}
static jobject osNetworkSystem_getSocketLocalAddressImpl(JNIEnv* env,
@@ -3215,7 +3015,7 @@
throwSocketException(env, convertError(errno));
return NULL;
}
- return newJavaLangInteger(env, timeout.tv_sec * 1000 + timeout.tv_usec/1000);
+ return newJavaLangInteger(env, toMs(timeout));
}
default: {
throwSocketException(env, SOCKERR_OPTUNSUPP);
@@ -3460,9 +3260,7 @@
}
case JAVASOCKOPT_SO_RCVTIMEOUT: {
- struct timeval timeout;
- timeout.tv_sec = intVal / 1000;
- timeout.tv_usec = (intVal % 1000) * 1000;
+ timeval timeout(toTimeval(intVal));
result = setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, &timeout,
sizeof(struct timeval));
if (0 != result) {
diff --git a/libcore/luni/src/main/native/org_apache_harmony_luni_util_fltparse.c b/libcore/luni/src/main/native/org_apache_harmony_luni_util_fltparse.c
index e92b776..ebbd6de 100644
--- a/libcore/luni/src/main/native/org_apache_harmony_luni_util_fltparse.c
+++ b/libcore/luni/src/main/native/org_apache_harmony_luni_util_fltparse.c
@@ -240,7 +240,7 @@
}
else if (e >= 0 && e < 39)
{
- result = (jfloat) (toDoubleHighPrecision (f, length) * pow (10.0, e));
+ result = (jfloat) (toDoubleHighPrecision (f, length) * pow (10.0, (double) e));
}
else if (e >= 39)
{
@@ -260,7 +260,7 @@
int dexp;
U_32 fmant, fovfl;
U_64 dmant;
- dresult = toDoubleHighPrecision (f, length) / pow (10.0, -e);
+ dresult = toDoubleHighPrecision (f, length) / pow (10.0, (double) -e);
if (IS_DENORMAL_DBL (dresult))
{
FLOAT_TO_INTBITS (result) = 0;
diff --git a/libcore/luni/src/main/native/sub.mk b/libcore/luni/src/main/native/sub.mk
index d277f82..184a13d 100644
--- a/libcore/luni/src/main/native/sub.mk
+++ b/libcore/luni/src/main/native/sub.mk
@@ -13,7 +13,7 @@
java_lang_Math.c \
java_lang_StrictMath.c \
java_net_InetAddress.cpp \
- java_net_NetworkInterface.c \
+ java_net_NetworkInterface.cpp \
cbigint.c \
commonDblParce.c \
org_apache_harmony_luni_util_fltparse.c \
diff --git a/libcore/luni/src/test/java/com/google/coretests/CoreTestRunner.java b/libcore/luni/src/test/java/com/google/coretests/CoreTestRunner.java
index d469c86..ad766aa 100644
--- a/libcore/luni/src/test/java/com/google/coretests/CoreTestRunner.java
+++ b/libcore/luni/src/test/java/com/google/coretests/CoreTestRunner.java
@@ -15,6 +15,8 @@
*/
package com.google.coretests;
+import java.util.ArrayList;
+import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -67,6 +69,11 @@
private int fTimeout;
private int fStep = 1;
+
+ /**
+ * The path to write XML reports to, or {@code null} for no reports.
+ */
+ private String xmlReportsDirectory;
/**
* Creates a new instance of our CoreTestRunner.
@@ -125,19 +132,32 @@
* Make sure the original suite is unreachable after we have
* created the new one, so GC can dispose terminated tests.
*/
- suite = new CoreTestSuite(suite, fFlags, fStep, null);
-
- return super.doRun(suite, wait);
+ CoreTestSuite coreTestSuite = new CoreTestSuite(suite, fFlags, fStep, null);
+
+ XmlReportPrinter xmlReportPrinter = xmlReportsDirectory != null
+ ? new XmlReportPrinter(coreTestSuite)
+ : null;
+
+ TestResult result = super.doRun(coreTestSuite, wait);
+
+ if (xmlReportPrinter != null) {
+ System.out.print("Printing XML Reports... ");
+ xmlReportPrinter.setResults(result);
+ int numFiles = xmlReportPrinter.generateReports(xmlReportsDirectory);
+ System.out.println(numFiles + " files written.");
+ }
+
+ return result;
}
-
+
/**
* Prints a help screen on the console.
*/
private void showHelp() {
- System.out.println("Usage: run-core-tests {<param>} <test>");
+ System.out.println("Usage: run-core-tests [OPTION]... [TEST]...");
System.out.println();
- System.out.println("Where <test> is a class name, optionally followed");
- System.out.println("by \"#\" and a method name, and <param> is one of");
+ System.out.println("Where each TEST is a class name, optionally followed");
+ System.out.println("by \"#\" and a method name, and each OPTION is one of");
System.out.println("the following:");
System.out.println();
System.out.println(" --include-all");
@@ -160,6 +180,7 @@
System.out.println(" --isolate-all");
System.out.println(" --isolate-none");
System.out.println(" --verbose");
+ System.out.println(" --xml-reports-directory <path>");
System.out.println(" --help");
System.out.println();
System.out.println("Default parameters are:");
@@ -185,26 +206,29 @@
}
/**
- * Tries to create a Test instance from a given string. The string might
+ * Tries to create a Test instance from the given strings. The strings might
* either specify a class only or a class plus a method name, separated by
* a "#".
*/
- private Test createTest(String testCase) throws Exception {
- int p = testCase.indexOf("#");
- if (p != -1) {
- String testName = testCase.substring(p + 1);
- testCase = testCase.substring(0, p);
-
- return TestSuite.createTest(Class.forName(testCase), testName);
- } else {
- return getTest(testCase);
+ private Test createTest(List<String> testCases) throws Exception {
+ TestSuite result = new TestSuite();
+ for (String testCase : testCases) {
+ int p = testCase.indexOf("#");
+ if (p != -1) {
+ String testName = testCase.substring(p + 1);
+ testCase = testCase.substring(0, p);
+
+ result.addTest(TestSuite.createTest(Class.forName(testCase), testName));
+ } else {
+ result.addTest(getTest(testCase));
+ }
}
-
+ return result;
}
@Override
protected TestResult start(String args[]) throws Exception {
- String testName = null;
+ List<String> testNames = new ArrayList<String>();
// String victimName = null;
boolean wait = false;
@@ -265,16 +289,18 @@
// victimName = args[++i];
} else if (args[i].equals("--dry-run")) {
fFlags = fFlags | CoreTestSuite.DRY_RUN;
+ } else if (args[i].equals("--xml-reports-directory")) {
+ xmlReportsDirectory = args[++i];
} else if (args[i].equals("--help")) {
showHelp();
System.exit(1);
} else {
- System.err.println("Unknown argument " + args[i] +
- ", try --help");
- System.exit(1);
+ unknownArgument(args[i]);
}
+ } else if (args[i].startsWith("-")) {
+ unknownArgument(args[i]);
} else {
- testName = args[i];
+ testNames.add(args[i]);
}
}
@@ -288,7 +314,7 @@
System.out.println();
try {
- return doRun(createTest(testName), wait);
+ return doRun(createTest(testNames), wait);
}
catch(Exception e) {
e.printStackTrace();
@@ -296,4 +322,8 @@
}
}
+ private static void unknownArgument(String arg) {
+ System.err.println("Unknown argument " + arg + ", try --help");
+ System.exit(1);
+ }
}
diff --git a/libcore/luni/src/test/java/com/google/coretests/CoreTestSuite.java b/libcore/luni/src/test/java/com/google/coretests/CoreTestSuite.java
index 3c9e7fa..fd7531f 100644
--- a/libcore/luni/src/test/java/com/google/coretests/CoreTestSuite.java
+++ b/libcore/luni/src/test/java/com/google/coretests/CoreTestSuite.java
@@ -98,6 +98,8 @@
public static final int REVERSE = 512;
public static final int DRY_RUN = 1024;
+
+ private final String name;
/**
* The total number of tests in the original suite.
@@ -154,7 +156,8 @@
*/
public CoreTestSuite(Test suite, int flags, int step, TestCase victim) {
super();
-
+
+ name = suite.toString();
fStep = step;
addAndFlatten(suite, flags);
fVictim = victim;
@@ -180,17 +183,13 @@
}
}
} else if (test instanceof TestCase) {
- TestCase caze = (TestCase)test;
+ TestCase testCase = (TestCase)test;
boolean ignoreMe = false;
- boolean isAndroidOnly = hasAnnotation(caze,
- AndroidOnly.class);
- boolean isBrokenTest = hasAnnotation(caze,
- BrokenTest.class);
- boolean isKnownFailure = hasAnnotation(caze,
- KnownFailure.class);
- boolean isSideEffect = hasAnnotation(caze,
- SideEffect.class);
+ boolean isAndroidOnly = hasAnnotation(testCase, AndroidOnly.class);
+ boolean isBrokenTest = hasAnnotation(testCase, BrokenTest.class);
+ boolean isKnownFailure = hasAnnotation(testCase, KnownFailure.class);
+ boolean isSideEffect = hasAnnotation(testCase, SideEffect.class);
boolean isNormalTest =
!(isAndroidOnly || isBrokenTest || isKnownFailure ||
isSideEffect);
@@ -269,27 +268,27 @@
public void run(TestResult result) {
// Run tests
int i = 0;
-
+
while (fTests.size() != 0 && !result.shouldStop()) {
TestCase test = (TestCase)fTests.elementAt(i);
Thread.currentThread().setContextClassLoader(
test.getClass().getClassLoader());
-
+
test.run(result);
/*
if (fVictim != null) {
TestResult dummy = fVictim.run();
-
+
if (dummy.failureCount() != 0) {
result.addError(fTests.elementAt(i), new RuntimeException(
- "Probable side effect",
+ "Probable side effect",
((TestFailure)dummy.failures().nextElement()).
thrownException()));
} else if (dummy.errorCount() != 0) {
result.addError(fTests.elementAt(i), new RuntimeException(
- "Probable side effect",
+ "Probable side effect",
((TestFailure)dummy.errors().nextElement()).
thrownException()));
}
@@ -352,4 +351,7 @@
return fTests.size();
}
+ @Override public String toString() {
+ return name;
+ }
}
diff --git a/libcore/luni/src/test/java/com/google/coretests/XmlReportPrinter.java b/libcore/luni/src/test/java/com/google/coretests/XmlReportPrinter.java
new file mode 100644
index 0000000..315371f
--- /dev/null
+++ b/libcore/luni/src/test/java/com/google/coretests/XmlReportPrinter.java
@@ -0,0 +1,249 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.google.coretests;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestFailure;
+import junit.framework.TestResult;
+import junit.runner.BaseTestRunner;
+import org.kxml2.io.KXmlSerializer;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
+
+
+/**
+ * Writes JUnit results to a series of XML files in a format consistent with
+ * Ant's XMLJUnitResultFormatter.
+ *
+ * <p>Unlike Ant's formatter, this class does not report the execution time of
+ * tests.
+ */
+public class XmlReportPrinter {
+
+ private static final String TESTSUITE = "testsuite";
+ private static final String TESTCASE = "testcase";
+ private static final String ERROR = "error";
+ private static final String FAILURE = "failure";
+ private static final String ATTR_NAME = "name";
+ private static final String ATTR_TIME = "time";
+ private static final String ATTR_ERRORS = "errors";
+ private static final String ATTR_FAILURES = "failures";
+ private static final String ATTR_TESTS = "tests";
+ private static final String ATTR_TYPE = "type";
+ private static final String ATTR_MESSAGE = "message";
+ private static final String PROPERTIES = "properties";
+ private static final String ATTR_CLASSNAME = "classname";
+ private static final String TIMESTAMP = "timestamp";
+ private static final String HOSTNAME = "hostname";
+
+ /** the XML namespace */
+ private static final String ns = null;
+
+ /** the test suites, which each contain tests */
+ private final Map<String, Suite> suites = new LinkedHashMap<String, Suite>();
+
+ /**
+ * Create a report printer that prints the specified test suite. Since the
+ * CoreTestSuite nulls-out tests after they're run (to limit memory
+ * consumption), it is necessary to create the report printer prior to test
+ * execution.
+ */
+ public XmlReportPrinter(CoreTestSuite allTests) {
+ // partition the tests by suite to be consistent with Ant's printer
+ for (Enumeration<Test> e = allTests.tests(); e.hasMoreElements(); ) {
+ TestId test = new TestId(e.nextElement());
+
+ // create the suite's entry in the map if necessary
+ Suite suite = suites.get(test.className);
+ if (suite == null) {
+ suite = new Suite(test.className);
+ suites.put(test.className, suite);
+ }
+
+ suite.tests.add(test);
+ }
+ }
+
+ public void setResults(TestResult result) {
+ populateFailures(true, result.errors());
+ populateFailures(false, result.failures());
+ }
+
+ /**
+ * Populate the list of failures in each of the suites.
+ */
+ private void populateFailures(boolean errors, Enumeration<TestFailure> failures) {
+ while (failures.hasMoreElements()) {
+ TestFailure failure = failures.nextElement();
+ TestId test = new TestId(failure.failedTest());
+ Suite suite = suites.get(test.className);
+
+ if (suite == null) {
+ throw new IllegalStateException( "received a failure for a "
+ + "test that wasn't in the original test suite!");
+ }
+
+ if (errors) {
+ suite.errors.put(test, failure);
+ } else {
+ suite.failures.put(test, failure);
+ }
+ }
+ }
+
+ public int generateReports(String directory) {
+ File parent = new File(directory);
+ parent.mkdirs();
+
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+ TimeZone gmt = TimeZone.getTimeZone("GMT");
+ dateFormat.setTimeZone(gmt);
+ dateFormat.setLenient(true);
+ String timestamp = dateFormat.format(new Date());
+
+ for (Suite suite : suites.values()) {
+ FileOutputStream stream = null;
+ try {
+ stream = new FileOutputStream(new File(parent, "TEST-" + suite.name + ".xml"));
+
+ KXmlSerializer serializer = new KXmlSerializer();
+ serializer.setOutput(stream, "UTF-8");
+ serializer.startDocument("UTF-8", null);
+ serializer.setFeature(
+ "http://xmlpull.org/v1/doc/features.html#indent-output", true);
+ suite.print(serializer, timestamp);
+ serializer.endDocument();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (IOException ignored) {
+ }
+ }
+ }
+ }
+
+ return suites.size();
+ }
+
+ static class Suite {
+ private final String name;
+ private final List<TestId> tests = new ArrayList<TestId>();
+ private final Map<TestId, TestFailure> failures = new HashMap<TestId, TestFailure>();
+ private final Map<TestId, TestFailure> errors = new HashMap<TestId, TestFailure>();
+
+ Suite(String name) {
+ this.name = name;
+ }
+
+ void print(KXmlSerializer serializer, String timestamp) throws IOException {
+ serializer.startTag(ns, TESTSUITE);
+ serializer.attribute(ns, ATTR_NAME, name);
+ serializer.attribute(ns, ATTR_TESTS, Integer.toString(tests.size()));
+ serializer.attribute(ns, ATTR_FAILURES, Integer.toString(failures.size()));
+ serializer.attribute(ns, ATTR_ERRORS, Integer.toString(errors.size()));
+ serializer.attribute(ns, ATTR_TIME, "0");
+
+ serializer.attribute(ns, TIMESTAMP, timestamp);
+ serializer.attribute(ns, HOSTNAME, "localhost");
+ serializer.startTag(ns, PROPERTIES);
+ serializer.endTag(ns, PROPERTIES);
+
+ for (TestId testId : tests) {
+ TestFailure error = errors.get(testId);
+ TestFailure failure = failures.get(testId);
+
+ if (error != null) {
+ testId.printFailure(serializer, ERROR, error.thrownException());
+ } else if (failure != null) {
+ testId.printFailure(serializer, FAILURE, failure.thrownException());
+ } else {
+ testId.printSuccess(serializer);
+ }
+ }
+
+ serializer.endTag(ns, TESTSUITE);
+ }
+ }
+
+ private static class TestId {
+ private final String name;
+ private final String className;
+
+ TestId(Test test) {
+ this.name = test instanceof TestCase
+ ? ((TestCase) test).getName()
+ : test.toString();
+ this.className = test.getClass().getName();
+ }
+
+ void printSuccess(KXmlSerializer serializer) throws IOException {
+ serializer.startTag(ns, TESTCASE);
+ printAttributes(serializer);
+ serializer.endTag(ns, TESTCASE);
+ }
+
+ void printFailure(KXmlSerializer serializer, String type, Throwable t)
+ throws IOException {
+ serializer.startTag(ns, TESTCASE);
+ printAttributes(serializer);
+
+ serializer.startTag(ns, type);
+ String message = t.getMessage();
+ if (message != null && message.length() > 0) {
+ serializer.attribute(ns, ATTR_MESSAGE, t.getMessage());
+ }
+ serializer.attribute(ns, ATTR_TYPE, t.getClass().getName());
+ serializer.text(BaseTestRunner.getFilteredTrace(t));
+ serializer.endTag(ns, type);
+
+ serializer.endTag(ns, TESTCASE);
+ }
+
+ void printAttributes(KXmlSerializer serializer) throws IOException {
+ serializer.attribute(ns, ATTR_NAME, name);
+ serializer.attribute(ns, ATTR_CLASSNAME, className);
+ serializer.attribute(ns, ATTR_TIME, "0");
+ }
+
+ @Override public boolean equals(Object o) {
+ return o instanceof TestId
+ && ((TestId) o).name.equals(name)
+ && ((TestId) o).className.equals(className);
+ }
+
+ @Override public int hashCode() {
+ return name.hashCode() ^ className.hashCode();
+ }
+ }
+}
\ No newline at end of file
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/https/HttpsURLConnectionTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/https/HttpsURLConnectionTest.java
index c99a0c1..275ea9d 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/https/HttpsURLConnectionTest.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/internal/net/www/protocol/https/HttpsURLConnectionTest.java
@@ -20,11 +20,21 @@
import dalvik.annotation.AndroidOnly;
import dalvik.annotation.BrokenTest;
import dalvik.annotation.KnownFailure;
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+import junit.framework.TestCase;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManagerFactory;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
@@ -41,22 +51,16 @@
import java.net.Proxy;
import java.net.ServerSocket;
import java.net.Socket;
-import java.net.SocketTimeoutException;
import java.net.URL;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.util.Arrays;
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLServerSocket;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManagerFactory;
-
-import junit.framework.TestCase;
+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.TimeUnit;
/**
* Implementation independent test for HttpsURLConnection.
@@ -994,7 +998,7 @@
* Returns the file name of the key/trust store. The key store file
* (named as "key_store." + extension equals to the default KeyStore
* type installed in the system in lower case) is searched in classpath.
- * @throws AssertionFailedError if property was not set
+ * @throws junit.framework.AssertionFailedError if property was not set
* or file does not exist.
*/
private static String getKeyStoreFileName() {
@@ -1145,28 +1149,19 @@
ClientConnectionWork client = new ClientConnectionWork(clientConnection);
- server.start();
- client.start();
+ ExecutorService executorService = Executors.newFixedThreadPool(2);
+ try {
+ Future<Void> serverFuture = executorService.submit(server);
+ Future<Void> clientFuture = executorService.submit(client);
- client.join();
- server.join();
+ serverFuture.get(30, TimeUnit.SECONDS);
+ clientFuture.get(30, TimeUnit.SECONDS);
+ } catch (ExecutionException e) {
+ throw e.getCause();
+ } finally {
+ executorService.shutdown();
+ }
- if (client.thrown != null) {
- if (responseCode != OK_CODE) { // not OK response expected
- // it is probably expected exception, keep it as is
- throw client.thrown;
- }
- if ((client.thrown instanceof SocketTimeoutException)
- && (server.thrown != null)) {
- // server's exception is more informative in this case
- throw new Exception(server.thrown);
- } else {
- throw new Exception(client.thrown);
- }
- }
- if (server.thrown != null) {
- throw server.thrown;
- }
return server.peerSocket;
}
@@ -1190,7 +1185,7 @@
/**
* The base class for mock Client and Server.
*/
- static class Work extends Thread {
+ static class Work {
/**
* The header of OK HTTP response.
@@ -1242,11 +1237,6 @@
static final String clientsData = "_.-^ Client's Data ^-._";
/**
- * The exception thrown during peers interaction.
- */
- protected Throwable thrown;
-
- /**
* The print stream used for debug log.
* If it is null debug info will not be printed.
*/
@@ -1257,7 +1247,7 @@
*/
public synchronized void log(String message) {
if (DO_LOG && (out != null)) {
- System.out.println("[" + getName() + "]: " + message);
+ out.println("[" + this + "]: " + message);
}
}
}
@@ -1265,7 +1255,7 @@
/**
* The class used for server side works.
*/
- static class ServerWork extends Work {
+ static class ServerWork extends Work implements Callable<Void> {
// the server socket used for connection
private ServerSocket serverSocket;
@@ -1314,7 +1304,6 @@
this.actAsProxy = true;
}
this.actAsProxy = !(serverSocket instanceof SSLServerSocket);
- setName(this.actAsProxy ? "Proxy Server" : "Server");
}
/**
@@ -1337,7 +1326,7 @@
* If some exception occurs during the work it will be
* stored in the <code>thrown</code> field.
*/
- public void run() {
+ public Void call() throws Exception {
// the buffer used for reading the messages
byte[] buff = new byte[2048];
// the number of bytes read into the buffer
@@ -1371,14 +1360,13 @@
assertEquals(clientsData, message);
}
// just send the response
- os
- .write(("HTTP/1.1 " + responseCode + "\n" + httpsResponseTail)
- .getBytes());
+ os.write(("HTTP/1.1 " + responseCode + "\n" + httpsResponseTail)
+ .getBytes());
os.flush();
os.close();
// and return
log("Work is DONE !actAsProxy");
- return;
+ return null;
}
// Do proxy work
@@ -1389,7 +1377,7 @@
// read response
num = is.read(buff);
if (num == -1) {
- // this connection was closed,
+ // this connection was closed,
// do clean up and create new one:
closeSocket(peerSocket);
peerSocket = serverSocket.accept();
@@ -1455,11 +1443,7 @@
.getBytes());
}
log("Work is DONE actAsProxy");
- } catch (Throwable e) {
- if (DO_LOG) {
- e.printStackTrace();
- }
- thrown = e;
+ return null;
} finally {
closeSocket(peerSocket);
try {
@@ -1467,13 +1451,17 @@
} catch (IOException e) {}
}
}
+
+ @Override public String toString() {
+ return actAsProxy ? "Proxy Server" : "Server";
+ }
}
/**
* The class used for client side works. It could be used to test
* both HttpURLConnection and HttpsURLConnection.
*/
- static class ClientConnectionWork extends Work {
+ static class ClientConnectionWork extends Work implements Callable<Void> {
// connection to be used to contact the server side
private HttpURLConnection connection;
@@ -1484,7 +1472,6 @@
*/
public ClientConnectionWork(HttpURLConnection connection) {
this.connection = connection;
- setName("Client Connection");
log("Created over connection: " + connection.getClass());
}
@@ -1493,42 +1480,41 @@
* If some exception occurs during the work it will be
* stored in the <code>thrown<code> field.
*/
- public void run() {
- try {
- log("Opening the connection..");
- connection.connect();
- log("Connection has been ESTABLISHED, using proxy: "
- + connection.usingProxy());
- if (connection.getDoOutput()) {
- // connection configured to post data, do so
- connection.getOutputStream().write(clientsData.getBytes());
- }
- // read the content of HTTP(s) response
- InputStream is = connection.getInputStream();
- log("Input Stream obtained");
- byte[] buff = new byte[2048];
- int num = 0;
- int byt = 0;
- while ((num < buff.length) && (is.available() > 0)
- && ((byt = is.read()) != -1)) {
- buff[num++] = (byte) byt;
- }
- String message = new String(buff, 0, num);
- log("Got content:\n" + message);
- log("------------------");
- log("Response code: " + connection.getResponseCode());
-
- if (connection instanceof HttpsURLConnection) {
- assertEquals(httpsResponseContent, message);
- } else {
- assertEquals(plainResponseContent, message);
- }
- } catch (Throwable e) {
- if (DO_LOG) {
- e.printStackTrace();
- }
- thrown = e;
+ public Void call() throws Exception {
+ log("Opening the connection..");
+ connection.connect();
+ log("Connection has been ESTABLISHED, using proxy: "
+ + connection.usingProxy());
+ if (connection.getDoOutput()) {
+ // connection configured to post data, do so
+ connection.getOutputStream().write(clientsData.getBytes());
}
+ // read the content of HTTP(s) response
+ InputStream is = connection.getInputStream();
+ log("Input Stream obtained");
+ byte[] buff = new byte[2048];
+ int num = 0;
+ int byt = 0;
+ while ((num < buff.length) && (is.available() > 0)
+ && ((byt = is.read()) != -1)) {
+ buff[num++] = (byte) byt;
+ }
+ String message = new String(buff, 0, num);
+ log("Got content:\n" + message);
+ log("------------------");
+ log("Response code: " + connection.getResponseCode());
+
+ if (connection instanceof HttpsURLConnection) {
+ assertEquals(httpsResponseContent, message);
+ } else {
+ assertEquals(plainResponseContent, message);
+ }
+
+ return null;
+ }
+
+ @Override public String toString() {
+ return "Client Connection";
}
}
}
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/PackageTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/PackageTest.java
index cb35324..283c1db 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/PackageTest.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/PackageTest.java
@@ -312,7 +312,7 @@
method = "isCompatibleWith",
args = {java.lang.String.class}
)
- @KnownFailure("isCompatibleWith returns incorrect value.")
+ @KnownFailure("Dalvik packages are always version '0.0'.")
public void test_isCompatibleWithLjava_lang_String() throws Exception {
Package p = getTestPackage("hyts_c.jar", "p.C");
diff --git a/libcore/luni/src/test/java/tests/AllTests.java b/libcore/luni/src/test/java/tests/AllTests.java
index 893cdf0..7533eea 100644
--- a/libcore/luni/src/test/java/tests/AllTests.java
+++ b/libcore/luni/src/test/java/tests/AllTests.java
@@ -32,6 +32,7 @@
public static final Test suite() {
TestSuite suite = tests.TestSuiteFactory.createTestSuite();
+ // Harmony-written test suites (often with Android tests added in).
suite.addTest(tests.annotation.AllTests.suite());
suite.addTest(tests.archive.AllTests.suite());
suite.addTest(tests.concurrent.AllTests.suite());
@@ -53,8 +54,12 @@
suite.addTest(tests.text.AllTests.suite());
suite.addTest(tests.xml.AllTests.suite());
suite.addTest(tests.xnet.AllTests.suite());
-
+
+ // Android-written test suites.
+ suite.addTest(com.ibm.icu4jni.util.AllTests.suite());
+ suite.addTest(java.lang.reflect.AllTests.suite());
suite.addTest(org.apache.harmony.luni.platform.AllTests.suite());
+ suite.addTest(tests.api.org.apache.harmony.kernel.dalvik.AllTests.suite());
return suite;
}
diff --git a/libcore/luni/src/test/java/tests/api/java/io/FileTest.java b/libcore/luni/src/test/java/tests/api/java/io/FileTest.java
index 81f14e0..3063b89 100644
--- a/libcore/luni/src/test/java/tests/api/java/io/FileTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/io/FileTest.java
@@ -31,13 +31,14 @@
import java.net.URISyntaxException;
import java.net.URL;
-import tests.support.Support_Exec;
import dalvik.annotation.AndroidOnly;
import dalvik.annotation.KnownFailure;
import dalvik.annotation.TestLevel;
import dalvik.annotation.TestTargetClass;
import dalvik.annotation.TestTargetNew;
import dalvik.annotation.TestTargets;
+import static tests.support.Support_Exec.javaProcessBuilder;
+import static tests.support.Support_Exec.execAndGetOutput;
@TestTargetClass(File.class)
public class FileTest extends junit.framework.TestCase {
@@ -689,8 +690,6 @@
args = {}
)
public void test_delete() {
- // this test passes in the emulator, but it fails on the device
-
// Test for method boolean java.io.File.delete()
try {
File dir = new File(System.getProperty("java.io.tmpdir"), platformId
@@ -2467,12 +2466,14 @@
assertTrue("could not find the path of the test jar/apk", idx > 0);
classPath = classPath.substring(9, idx); // cutting off jar:file:
- Support_Exec.execJava(new String[] {
- "tests.support.Support_DeleteOnExitTest",
- dir.getAbsolutePath(), subDir.getAbsolutePath() },
- new String[] { System.getProperty("java.class.path"),
- classPath }, false);
- Thread.sleep(2000);
+ ProcessBuilder builder = javaProcessBuilder();
+ builder.command().add("-cp");
+ builder.command().add(System.getProperty("java.class.path"));
+ builder.command().add("tests.support.Support_DeleteOnExitTest");
+ builder.command().add(dir.getAbsolutePath());
+ builder.command().add(subDir.getAbsolutePath());
+ execAndGetOutput(builder);
+
assertFalse(dir.exists());
assertFalse(subDir.exists());
}
diff --git a/libcore/luni/src/test/java/tests/api/java/io/RandomAccessFileTest.java b/libcore/luni/src/test/java/tests/api/java/io/RandomAccessFileTest.java
index 3b545e3..dc35610 100644
--- a/libcore/luni/src/test/java/tests/api/java/io/RandomAccessFileTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/io/RandomAccessFileTest.java
@@ -1200,16 +1200,25 @@
} catch (IOException e) {
// Expected.
}
+ // BEGIN android-added
+ try {
+ // Android uses 32-bit off_t, so anything larger than a signed 32-bit int won't work.
+ raf.seek(((long) Integer.MAX_VALUE) + 1);
+ fail("Test 2: IOException expected.");
+ } catch (IOException e) {
+ // Expected.
+ }
+ // END android-added
raf.write(testString.getBytes(), 0, testLength);
raf.seek(12);
- assertEquals("Test 2: Seek failed to set file pointer.", 12,
+ assertEquals("Test 3: Seek failed to set file pointer.", 12,
raf.getFilePointer());
raf.close();
try {
raf.seek(1);
- fail("Test 1: IOException expected.");
+ fail("Test 4: IOException expected.");
} catch (IOException e) {
// Expected.
}
@@ -1296,10 +1305,21 @@
assertEquals("Test 7: Incorrect file length;",
testLength + 2, raf.length());
+ // BEGIN android-added
+ // Exception testing.
+ try {
+ // Android uses 32-bit off_t, so anything larger than a signed 32-bit int won't work.
+ raf.setLength(((long) Integer.MAX_VALUE) + 1);
+ fail("Test 8: IOException expected.");
+ } catch (IOException e) {
+ // Expected.
+ }
+ // END android-added
+
// Exception testing.
try {
raf.setLength(-1);
- fail("Test 8: IllegalArgumentException expected.");
+ fail("Test 9: IllegalArgumentException expected.");
} catch (IllegalArgumentException e) {
// Expected.
}
@@ -1307,7 +1327,7 @@
raf.close();
try {
raf.setLength(truncLength);
- fail("Test 9: IOException expected.");
+ fail("Test 10: IOException expected.");
} catch (IOException e) {
// Expected.
}
@@ -1501,4 +1521,4 @@
super.tearDown();
}
-}
\ No newline at end of file
+}
diff --git a/libcore/luni/src/test/java/tests/api/java/lang/Process2Test.java b/libcore/luni/src/test/java/tests/api/java/lang/Process2Test.java
index 51b29d8..2e60e77 100644
--- a/libcore/luni/src/test/java/tests/api/java/lang/Process2Test.java
+++ b/libcore/luni/src/test/java/tests/api/java/lang/Process2Test.java
@@ -30,6 +30,7 @@
import java.io.OutputStream;
import tests.support.Support_Exec;
+import static tests.support.Support_Exec.javaProcessBuilder;
@TestTargetClass(Process.class)
public class Process2Test extends junit.framework.TestCase {
@@ -60,23 +61,12 @@
)
})
@AndroidOnly("dalvikvm specific")
- public void test_isBufferedStreams() {
- // Regression test for HARMONY-2735.
- try {
- Object[] execArgs = Support_Exec.execJava2(new String[0], null, true);
- Process p = (Process) execArgs[0];
- InputStream in = p.getInputStream();
- assertNotNull(in);
- in = p.getErrorStream();
- assertNotNull(in);
- OutputStream out = p.getOutputStream();
- assertNotNull(out);
- in.close();
- out.close();
- p.destroy();
- } catch (Exception ex) {
- fail("Unexpected exception got: " + ex);
- }
+ public void test_streams()
+ throws IOException, InterruptedException {
+ Process p = javaProcessBuilder().start();
+ assertNotNull(p.getInputStream());
+ assertNotNull(p.getErrorStream());
+ assertNotNull(p.getOutputStream());
}
@TestTargetNew(
diff --git a/libcore/luni/src/test/java/tests/api/java/util/ArrayListTest.java b/libcore/luni/src/test/java/tests/api/java/util/ArrayListTest.java
index 8aa77cc..0356731 100644
--- a/libcore/luni/src/test/java/tests/api/java/util/ArrayListTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/util/ArrayListTest.java
@@ -19,7 +19,7 @@
import dalvik.annotation.TestTargetNew;
import dalvik.annotation.TestTargets;
import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetClass;
import java.util.ArrayList;
import java.util.Arrays;
@@ -33,13 +33,13 @@
import tests.support.Support_ListTest;
-@TestTargetClass(ArrayList.class)
+@TestTargetClass(ArrayList.class)
public class ArrayListTest extends junit.framework.TestCase {
List alist;
Object[] objArray;
-
+
/**
* @tests java.util.ArrayList#ArrayList()
*/
@@ -72,7 +72,7 @@
// Test for method java.util.ArrayList(int)
ArrayList al = new ArrayList(5);
assertEquals("Incorrect arrayList created", 0, al.size());
-
+
try {
new ArrayList(-10);
fail("IllegalArgumentException expected");
@@ -130,14 +130,14 @@
assertNull("Should have returned null", alist.get(25));
assertTrue("Should have returned the old item from slot 25", alist
.get(26) == oldItem);
-
+
try {
alist.add(-1, null);
fail("IndexOutOfBoundsException expected");
} catch (IndexOutOfBoundsException e) {
//expected
}
-
+
try {
alist.add(alist.size() + 1, null);
fail("IndexOutOfBoundsException expected");
@@ -198,9 +198,9 @@
assertTrue("Incorrect size: " + alist.size(), alist.size() == 205);
assertNull("Item at slot 100 should be null", alist.get(100));
assertNull("Item at slot 101 should be null", alist.get(101));
- assertEquals("Item at slot 102 should be 'yoink'",
+ assertEquals("Item at slot 102 should be 'yoink'",
"yoink", alist.get(102));
- assertEquals("Item at slot 103 should be 'kazoo'",
+ assertEquals("Item at slot 103 should be 'kazoo'",
"kazoo", alist.get(103));
assertNull("Item at slot 104 should be null", alist.get(104));
alist.addAll(205, listWithNulls);
@@ -228,24 +228,29 @@
}
}
- /**
- * @tests java.util.ArrayList#addAll(int, java.util.Collection)
- */
- @TestTargetNew(
- level = TestLevel.PARTIAL_COMPLETE,
- notes = "Verifies IndexOutOfBoundsException.",
- method = "addAll",
- args = {int.class, java.util.Collection.class}
- )
- public void test_addAllILjava_util_Collection_2() {
- // Regression for HARMONY-467
- ArrayList obj = new ArrayList();
- try {
- obj.addAll((int) -1, (Collection) null);
- fail("IndexOutOfBoundsException expected");
- } catch (IndexOutOfBoundsException e) {
- }
- }
+// BEGIN android-removed
+// The spec does not mandate that IndexOutOfBoundsException be thrown in
+// preference to NullPointerException when the caller desserves both.
+//
+// /**
+// * @tests java.util.ArrayList#addAll(int, java.util.Collection)
+// */
+// @TestTargetNew(
+// level = TestLevel.PARTIAL_COMPLETE,
+// notes = "Verifies IndexOutOfBoundsException.",
+// method = "addAll",
+// args = {int.class, java.util.Collection.class}
+// )
+// public void test_addAllILjava_util_Collection_2() {
+// // Regression for HARMONY-467
+// ArrayList obj = new ArrayList();
+// try {
+// obj.addAll((int) -1, (Collection) null);
+// fail("IndexOutOfBoundsException expected");
+// } catch (IndexOutOfBoundsException e) {
+// }
+// }
+// END android-removed
/**
* @tests java.util.ArrayList#addAll(java.util.Collection)
@@ -287,17 +292,17 @@
.get(101) == i.next());
assertTrue("Item at slot 103 is wrong: " + alist.get(102), alist
.get(102) == i.next());
-
-
+
+
// Regression test for Harmony-3481
ArrayList<Integer> originalList = new ArrayList<Integer>(12);
for (int j = 0; j < 12; j++) {
originalList.add(j);
}
-
+
originalList.remove(0);
originalList.remove(0);
-
+
ArrayList<Integer> additionalList = new ArrayList<Integer>(11);
for (int j = 0; j < 11; j++) {
additionalList.add(j);
@@ -672,7 +677,7 @@
assertTrue("Returned incorrect array: " + i,
retArray[i] == objArray[i]);
}
-
+
String[] strArray = new String[100];
try {
alist.toArray(strArray);
@@ -746,16 +751,16 @@
list.remove(0);
assertEquals(1, list.size());
-
+
ArrayList collection = new ArrayList();
collection.add("1");
collection.add("2");
collection.add("3");
assertEquals(3, collection.size());
-
+
list.addAll(0, collection);
assertEquals(4, list.size());
-
+
list.remove(0);
list.remove(0);
assertEquals(2, list.size());
@@ -769,13 +774,13 @@
collection.add("10");
collection.add("11");
collection.add("12");
-
+
assertEquals(12, collection.size());
-
+
list.addAll(0, collection);
assertEquals(14, list.size());
}
-
+
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
@@ -818,7 +823,7 @@
mal.add("f");
mal.add("g");
mal.add("h");
-
+
mal.removeRange(2, 4);
String[] result = new String[6];
@@ -827,30 +832,30 @@
new String[] { "a", "b", "e", "f", "g", "h"}));
}
-
+
/**
* Sets up the fixture, for example, open a network connection. This method
* is called before a test is executed.
*/
protected void setUp() throws Exception {
super.setUp();
-
+
objArray = new Object[100];
for (int i = 0; i < objArray.length; i++) {
objArray[i] = new Integer(i);
}
-
+
alist = new ArrayList();
for (int i = 0; i < objArray.length; i++) {
alist.add(objArray[i]);
}
}
-
+
@Override
protected void tearDown() throws Exception {
objArray = null;
alist = null;
-
+
super.tearDown();
}
}
diff --git a/libcore/luni/src/test/java/tests/api/java/util/CollectionsTest.java b/libcore/luni/src/test/java/tests/api/java/util/CollectionsTest.java
index 2b1b47e..7fc60d8 100644
--- a/libcore/luni/src/test/java/tests/api/java/util/CollectionsTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/util/CollectionsTest.java
@@ -41,6 +41,7 @@
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
+import java.util.Arrays;
import org.apache.harmony.luni.internal.nls.Messages;
@@ -807,18 +808,19 @@
LinkedList ll2 = new LinkedList();
ll2.addAll(ll);
testShuffle(ll2, "Random Access", false);
+ }
- Mock_ArrayList mal = new Mock_ArrayList();
-
- mal.add("First");
- mal.add("Second");
-
- try {
- Collections.shuffle(mal);
- fail("UnsupportedOperationException expected");
- } catch (UnsupportedOperationException e) {
- //expected
- }
+ public void testShuffleRandomAccessWithSeededRandom() {
+ List<String> list = Arrays.asList("A", "B", "C", "D", "E", "F", "G");
+ Collections.shuffle(list, new Random(0));
+ assertEquals(Arrays.asList("B", "A", "D", "C", "G", "E", "F"), list);
+ }
+
+ public void testShuffleWithSeededRandom() {
+ List<String> list = new LinkedList<String>(Arrays.asList(
+ "A", "B", "C", "D", "E", "F", "G"));
+ Collections.shuffle(list, new Random(0));
+ assertEquals(Arrays.asList("B", "A", "D", "C", "G", "E", "F"), list);
}
private void testShuffle(List list, String type, boolean random) {
@@ -837,15 +839,15 @@
sorted = false;
}
}
- assertTrue("Shuffling sorted " + type
- + " list resulted in sorted list (should be unlikely)", !sorted);
+ assertFalse("Shuffling sorted " + type
+ + " list resulted in sorted list (should be unlikely)", sorted);
for (int counter = 0; counter < 20; counter++) {
index = 30031 * counter % (size + 1); // 30031 is a large prime
if (list.get(index) != ll.get(index))
allMatch = false;
}
- assertTrue("Too many element positions match in shuffled " + type
- + " list", !allMatch);
+ assertFalse("Too many element positions match in shuffled " + type
+ + " list", allMatch);
}
/**
diff --git a/libcore/luni/src/test/java/tests/api/java/util/FormatterTest.java b/libcore/luni/src/test/java/tests/api/java/util/FormatterTest.java
index b2030c9..6f86818 100644
--- a/libcore/luni/src/test/java/tests/api/java/util/FormatterTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/util/FormatterTest.java
@@ -800,6 +800,36 @@
}
}
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Tests that supplying a Formattable works. See http://code.google.com/p/android/issues/detail?id=1767.",
+ method = "format",
+ args = {}
+ )
+ public void test_Formattable() {
+ Formattable ones = new Formattable() {
+ public void formatTo(Formatter formatter, int flags, int width, int precision) throws IllegalFormatException {
+ try {
+ formatter.out().append("111");
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ Formattable twos = new Formattable() {
+ public void formatTo(Formatter formatter, int flags, int width, int precision) throws IllegalFormatException {
+ try {
+ formatter.out().append("222");
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+
+ assertEquals("aaa 111?", new Formatter().format("aaa %s?", ones).toString());
+ assertEquals("aaa 111 bbb 222?", new Formatter().format("aaa %s bbb %s?", ones, twos).toString());
+ }
+
/**
* @tests java.util.Formatter#out()
*/
diff --git a/libcore/luni/src/test/java/tests/api/java/util/TimeZoneTest.java b/libcore/luni/src/test/java/tests/api/java/util/TimeZoneTest.java
index efdb8a1..75e9ae3 100644
--- a/libcore/luni/src/test/java/tests/api/java/util/TimeZoneTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/util/TimeZoneTest.java
@@ -383,6 +383,19 @@
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
+ method = "useDaylightTime",
+ args = {}
+ )
+ public void test_useDaylightTime() {
+ // http://code.google.com/p/android/issues/detail?id=877
+
+ TimeZone asiaTaipei = TimeZone.getTimeZone("Asia/Taipei");
+ assertFalse("Taiwan doesn't use DST", asiaTaipei.useDaylightTime());
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
method = "setID",
args = {java.lang.String.class}
)
diff --git a/libcore/math/src/main/java/java/math/BigInt.java b/libcore/math/src/main/java/java/math/BigInt.java
index cb7990a..581c22f 100644
--- a/libcore/math/src/main/java/java/math/BigInt.java
+++ b/libcore/math/src/main/java/java/math/BigInt.java
@@ -225,12 +225,6 @@
return a;
}
- public byte[] bigEndianTwosComplement() {
- byte[] a = NativeBN.bn2twosComp(this.bignum, null);
- return a;
- }
-
-
public int sign() {
return NativeBN.sign(this.bignum);
}
diff --git a/libcore/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/DatagramChannelTest.java b/libcore/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/DatagramChannelTest.java
index 36e0082..49c5faa 100644
--- a/libcore/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/DatagramChannelTest.java
+++ b/libcore/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/DatagramChannelTest.java
@@ -768,7 +768,7 @@
assertFalse(s.getBroadcast());
assertFalse(s.getReuseAddress());
assertNull(s.getInetAddress());
- assertEquals(s.getLocalAddress().getHostAddress(), "0.0.0.0");
+ assertTrue(s.getLocalAddress().isAnyLocalAddress());
assertEquals(s.getLocalPort(), 0);
assertNull(s.getLocalSocketAddress());
assertEquals(s.getPort(), -1);
diff --git a/libcore/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java b/libcore/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java
index 91d6d06..a846e70 100644
--- a/libcore/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java
+++ b/libcore/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java
@@ -1155,6 +1155,25 @@
} catch (IllegalArgumentException e) {
// expected
}
+
+ // BEGIN android-added
+ // Android uses 32-bit off_t, so anything larger than a signed 32-bit int won't work...
+ // ...except for the special case of length == Long.MAX_VALUE, which is used to mean "the
+ // whole file". The special case is tested elsewhere.
+ long tooBig = ((long) Integer.MAX_VALUE) + 1;
+ try {
+ readWriteFileChannel.tryLock(tooBig, 1, false);
+ fail("should throw IOException");
+ } catch (IOException e) {
+ // expected
+ }
+ try {
+ readWriteFileChannel.tryLock(0, tooBig, false);
+ fail("should throw IOException");
+ } catch (IOException e) {
+ // expected
+ }
+ // END android-added
}
/**
diff --git a/libcore/openssl/src/main/java/org/openssl/NativeBN.java b/libcore/openssl/src/main/java/org/openssl/NativeBN.java
index 44464e0..3597e3c 100644
--- a/libcore/openssl/src/main/java/org/openssl/NativeBN.java
+++ b/libcore/openssl/src/main/java/org/openssl/NativeBN.java
@@ -79,9 +79,6 @@
public static native int[] bn2litEndInts(int a, int[] to);
- public static native byte[] bn2twosComp(int a, byte[] to);
-
-
public static native int sign(int a);
// Returns -1, 0, 1 AND NOT boolean.
// #define BN_is_negative(a) ((a)->neg != 0)
diff --git a/libcore/openssl/src/main/native/BNInterface.c b/libcore/openssl/src/main/native/BNInterface.c
index 4132e4f..1a3eb16 100644
--- a/libcore/openssl/src/main/native/BNInterface.c
+++ b/libcore/openssl/src/main/native/BNInterface.c
@@ -33,12 +33,6 @@
static void
-throwOutOfMemoryException(JNIEnv* env, const char* message)
-{
- jniThrowException(env, "java/lang/OutOfMemoryError", message);
-}
-
-static void
throwNewNullPointerException (JNIEnv* env, const char* message)
{
jniThrowException(env, "java/lang/NullPointerException", message);
@@ -456,27 +450,6 @@
}
}
-/**
- * public static native byte[] bn2twosComp(int, byte[])
- */
-static jbyteArray NativeBN_bn2twosComp(JNIEnv* env, jclass cls, BIGNUM* a, jbyteArray to) {
- if (!oneValidHandle(env, a)) return NULL;
- jbyteArray returnJBytes = to;
- unsigned char * tmpBytes;
- int len, byteCnt;
- byteCnt = BN_num_bytes(a);
-// FIXME: Currently ignoring array passed in to:
- returnJBytes = (*env)->NewByteArray(env, byteCnt);
-// FIXME: is it neccessary to check for returnJBytes != NULL?
- tmpBytes = (unsigned char *)((*env)->GetPrimitiveArrayCritical(env, returnJBytes, NULL));
- if (tmpBytes != NULL) {
- len = BN_bn2bin(a, tmpBytes);
- (*env)->ReleasePrimitiveArrayCritical(env, returnJBytes, tmpBytes, 0);
- return returnJBytes;
- }
- else return NULL;
-}
-
/**
* public static native int sign(int)
@@ -833,7 +806,6 @@
{ "BN_bn2hex", "(I)Ljava/lang/String;", (void*)NativeBN_BN_bn2hex },
{ "BN_bn2bin", "(I[B)[B", (void*)NativeBN_BN_bn2bin },
{ "bn2litEndInts", "(I[I)[I", (void*)NativeBN_bn2litEndInts },
- { "bn2twosComp", "(I[B)[B", (void*)NativeBN_bn2twosComp },
{ "sign", "(I)I", (void*)NativeBN_sign },
{ "BN_set_negative", "(II)V", (void*)NativeBN_BN_set_negative },
{ "twosCompFitsIntoBytes", "(II)Z", (void*)NativeBN_twosCompFitsIntoBytes },
diff --git a/libcore/regex/src/main/java/java/util/regex/MatchResult.java b/libcore/regex/src/main/java/java/util/regex/MatchResult.java
index fa67ba6..76c17a8 100644
--- a/libcore/regex/src/main/java/java/util/regex/MatchResult.java
+++ b/libcore/regex/src/main/java/java/util/regex/MatchResult.java
@@ -1,17 +1,18 @@
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
*
- * 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
*
- * 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.
+ * 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 java.util.regex;
@@ -22,91 +23,75 @@
* pair of parentheses in the regular expression and an additional group for
* the whole regular expression. The start, end, and contents of each group
* can be queried.
- *
+ *
* @see Matcher
* @see Matcher#toMatchResult()
- *
- * @since Android 1.0
*/
public interface MatchResult {
/**
* Returns the index of the first character following the text that matched
- * the whole regular expression.
- *
+ * the whole regular expression.
+ *
* @return the character index.
- *
- * @since Android 1.0
*/
int end();
/**
* Returns the index of the first character following the text that matched
* a given group.
- *
+ *
* @param group
* the group, ranging from 0 to groupCount() - 1, with 0
* representing the whole pattern.
- *
+ *
* @return the character index.
- *
- * @since Android 1.0
*/
int end(int group);
/**
- * Returns the text that matched the whole regular expression.
- *
+ * Returns the text that matched the whole regular expression.
+ *
* @return the text.
- *
- * @since Android 1.0
*/
String group();
/**
* Returns the text that matched a given group of the regular expression.
- *
+ *
* @param group
* the group, ranging from 0 to groupCount() - 1, with 0
* representing the whole pattern.
- *
+ *
* @return the text that matched the group.
- *
- * @since Android 1.0
*/
String group(int group);
/**
* Returns the number of groups in the result, which is always equal to
* the number of groups in the original regular expression.
- *
+ *
* @return the number of groups.
- *
- * @since Android 1.0
*/
int groupCount();
/**
* Returns the index of the first character of the text that matched
- * the whole regular expression.
- *
+ * the whole regular expression.
+ *
* @return the character index.
- *
- * @since Android 1.0
*/
int start();
/**
* Returns the index of the first character of the text that matched a given
* group.
- *
+ *
* @param group
* the group, ranging from 0 to groupCount() - 1, with 0
* representing the whole pattern.
- *
+ *
* @return the character index.
- *
- * @since Android 1.0
*/
int start(int group);
}
diff --git a/libcore/regex/src/main/java/java/util/regex/Matcher.java b/libcore/regex/src/main/java/java/util/regex/Matcher.java
index e3e4874..be5c782 100644
--- a/libcore/regex/src/main/java/java/util/regex/Matcher.java
+++ b/libcore/regex/src/main/java/java/util/regex/Matcher.java
@@ -44,8 +44,6 @@
* {@code Pattern} was successful and at which position the next attempt would
* resume the search. Depending on the application's needs, it may become
* necessary to explicitly {@link #reset()} this state from time to time.
- *
- * @since Android 1.0
*/
public final class Matcher implements MatchResult {
@@ -128,39 +126,99 @@
}
/**
+ * Appends a literal part of the input plus a replacement for the current
+ * match to a given {@link StringBuffer}. The literal part is exactly the
+ * part of the input between the previous match and the current match. The
+ * method can be used in conjunction with {@link #find()} and
+ * {@link #appendTail(StringBuffer)} to walk through the input and replace
+ * all occurrences of the {@code Pattern} with something else.
+ *
+ * @param buffer
+ * the {@code StringBuffer} to append to.
+ * @param replacement
+ * the replacement text.
+ * @return the {@code Matcher} itself.
+ * @throws IllegalStateException
+ * if no successful match has been made.
+ */
+ public Matcher appendReplacement(StringBuffer buffer, String replacement) {
+ buffer.append(input.substring(appendPos, start()));
+ appendEvaluated(buffer, replacement);
+ appendPos = end();
+
+ return this;
+ }
+
+ /**
+ * Internal helper method to append a given string to a given string buffer.
+ * If the string contains any references to groups, these are replaced by
+ * the corresponding group's contents.
+ *
+ * @param buffer
+ * the string buffer.
+ * @param s
+ * the string to append.
+ */
+ private void appendEvaluated(StringBuffer buffer, String s) {
+ boolean escape = false;
+ boolean dollar = false;
+
+ for (int i = 0; i < s.length(); i++) {
+ char c = s.charAt(i);
+ if (c == '\\' && !escape) {
+ escape = true;
+ } else if (c == '$' && !escape) {
+ dollar = true;
+ } else if (c >= '0' && c <= '9' && dollar) {
+ buffer.append(group(c - '0'));
+ dollar = false;
+ } else {
+ buffer.append(c);
+ dollar = false;
+ escape = false;
+ }
+ }
+
+ // This seemingly stupid piece of code reproduces a JDK bug.
+ if (escape) {
+ throw new ArrayIndexOutOfBoundsException(s.length());
+ }
+ }
+
+ /**
* Resets the Matcher. A new input sequence and a new region can be
* specified. Results of a previous find get lost. The next attempt to find
* an occurrence of the Pattern in the string will start at the beginning of
* the region. This is the internal version of reset() to which the several
* public versions delegate.
- *
+ *
* @param input
* the input sequence.
* @param start
* the start of the region.
* @param end
* the end of the region.
- *
+ *
* @return the matcher itself.
*/
private Matcher reset(CharSequence input, int start, int end) {
if (input == null) {
throw new IllegalArgumentException();
}
-
- if (start < 0 || end < 0 || start > input.length() ||
+
+ if (start < 0 || end < 0 || start > input.length() ||
end > input.length() || start > end) {
throw new IllegalArgumentException();
}
// Maybe should have a reset() here, but it makes thing worse...
// NativeRegEx.reset(nativePattern, 0);
-
+
if (!input.equals(this.input)) {
this.input = input.toString();
-
+
NativeRegEx.setText(nativePattern, this.input);
-
+
regionStart = 0;
regionEnd = input.length();
}
@@ -176,22 +234,8 @@
matchFound = false;
findPos = regionStart;
appendPos = 0;
-
- return this;
- }
- /**
- * Resets the {@code Matcher}. This results in the region being set to the
- * whole input. Results of a previous find get lost. The next attempt to
- * find an occurrence of the {@link Pattern} in the string will start at the
- * beginning of the input.
- *
- * @return the {@code Matcher} itself.
- *
- * @since Android 1.0
- */
- public Matcher reset() {
- return reset(input, 0, input.length());
+ return this;
}
/**
@@ -204,73 +248,24 @@
* the new input sequence.
*
* @return the {@code Matcher} itself.
- *
- * @since Android 1.0
*/
public Matcher reset(CharSequence input) {
return reset(input, 0, input.length());
}
/**
- * Sets a new pattern for the {@code Matcher}. Results of a previous find
- * get lost. The next attempt to find an occurrence of the {@link Pattern}
- * in the string will start at the beginning of the input.
- *
- * @param pattern
- * the new {@code Pattern}.
- *
+ * Resets the {@code Matcher}. This results in the region being set to the
+ * whole input. Results of a previous find get lost. The next attempt to
+ * find an occurrence of the {@link Pattern} in the string will start at the
+ * beginning of the input.
+ *
* @return the {@code Matcher} itself.
- *
- * @since Android 1.0
*/
- public Matcher usePattern(Pattern pattern) {
- if (pattern == null) {
- throw new IllegalArgumentException();
- }
-
- this.pattern = pattern;
-
- if (nativePattern != 0) {
- NativeRegEx.close(nativePattern);
- }
- nativePattern = NativeRegEx.clone(pattern.mNativePattern);
-
- if (input != null) {
- NativeRegEx.setText(nativePattern, input);
- NativeRegEx.setRegion(nativePattern, regionStart, regionEnd);
- NativeRegEx.useAnchoringBounds(nativePattern, anchoringBounds);
- NativeRegEx.useTransparentBounds(nativePattern, transparentBounds);
- }
-
- matchOffsets = new int[(this.pattern.mGroupCount + 1) * 2];
- matchFound = false;
- return this;
+ public Matcher reset() {
+ return reset(input, 0, input.length());
}
/**
- * Returns the {@link Pattern} instance used inside this matcher.
- *
- * @return the {@code Pattern} instance.
- *
- * @since Android 1.0
- */
- public Pattern pattern() {
- return pattern;
- }
-
- /**
- * Returns the number of groups in the results, which is always equal to
- * the number of groups in the original regular expression.
- *
- * @return the number of groups.
- *
- * @since Android 1.0
- */
- public int groupCount() {
- return pattern.mGroupCount;
- }
-
- /**
* Resets this matcher and sets a region. Only characters inside the region
* are considered for a match.
*
@@ -279,109 +274,150 @@
* @param end
* the first character after the end of the region.
* @return the {@code Matcher} itself.
- * @since Android 1.0
*/
public Matcher region(int start, int end) {
return reset(input, start, end);
}
- /**
- * Returns this matcher's region start, that is, the first character that is
- * considered for a match.
- *
- * @return the start of the region.
- * @since Android 1.0
- */
- public int regionStart() {
- return regionStart;
- }
/**
- * Returns this matcher's region end, that is, the first character that is
- * not considered for a match.
- *
- * @return the end of the region.
- * @since Android 1.0
- */
- public int regionEnd() {
- return regionEnd;
- }
-
- /**
- * Determines whether this matcher has anchoring bounds enabled or not. When
- * anchoring bounds are enabled, the start and end of the input match the
- * '^' and '$' meta-characters, otherwise not. Anchoring bounds are enabled
- * by default.
- *
- * @param value
- * the new value for anchoring bounds.
- * @return the {@code Matcher} itself.
- * @since Android 1.0
- */
- public Matcher useAnchoringBounds(boolean value) {
- anchoringBounds = value;
- NativeRegEx.useAnchoringBounds(nativePattern, value);
- return this;
- }
-
- /**
- * Indicates whether this matcher has anchoring bounds enabled. When
- * anchoring bounds are enabled, the start and end of the input match the
- * '^' and '$' meta-characters, otherwise not. Anchoring bounds are enabled
- * by default.
- *
- * @return true if (and only if) the {@code Matcher} uses anchoring bounds.
- * @since Android 1.0
- */
- public boolean hasAnchoringBounds() {
- return anchoringBounds;
- }
-
- /**
- * Determines whether this matcher has transparent bounds enabled or not.
- * When transparent bounds are enabled, the parts of the input outside the
- * region are subject to lookahead and lookbehind, otherwise they are not.
- * Transparent bounds are disabled by default.
- *
- * @param value
- * the new value for transparent bounds.
- * @return the {@code Matcher} itself.
- * @since Android 1.0
- */
- public Matcher useTransparentBounds(boolean value) {
- transparentBounds = value;
- NativeRegEx.useTransparentBounds(nativePattern, value);
- return this;
- }
-
- /**
- * Indicates whether this matcher has transparent bounds enabled. When
- * transparent bounds are enabled, the parts of the input outside the region
- * are subject to lookahead and lookbehind, otherwise they are not.
- * Transparent bounds are disabled by default.
- *
- * @return true if (and only if) the {@code Matcher} uses anchoring bounds.
- * @since Android 1.0
- */
- public boolean hasTransparentBounds() {
- return transparentBounds;
- }
-
- /**
- * Makes sure that a successful match has been made. Is invoked internally
- * from various places in the class.
- *
+ * Appends the (unmatched) remainder of the input to the given
+ * {@link StringBuffer}. The method can be used in conjunction with
+ * {@link #find()} and {@link #appendReplacement(StringBuffer, String)} to
+ * walk through the input and replace all matches of the {@code Pattern}
+ * with something else.
+ *
+ * @param buffer
+ * the {@code StringBuffer} to append to.
+ * @return the {@code StringBuffer}.
* @throws IllegalStateException
* if no successful match has been made.
- *
- * @since Android 1.0
*/
- private void ensureMatch() throws IllegalStateException {
- if (!matchFound) {
- throw new IllegalStateException("No successful match so far");
+ public StringBuffer appendTail(StringBuffer buffer) {
+ if (appendPos < regionEnd) {
+ buffer.append(input.substring(appendPos, regionEnd));
+ }
+
+ return buffer;
+ }
+
+ /**
+ * Replaces the first occurrence of this matcher's pattern in the input with
+ * a given string.
+ *
+ * @param replacement
+ * the replacement text.
+ * @return the modified input string.
+ */
+ public String replaceFirst(String replacement) {
+ StringBuffer buffer = new StringBuffer(input.length());
+
+ findPos = 0;
+ appendPos = 0;
+ matchFound = false;
+ searching = false;
+
+ if (find()) {
+ appendReplacement(buffer, replacement);
+ }
+
+ return appendTail(buffer).toString();
+ }
+
+ /**
+ * Replaces all occurrences of this matcher's pattern in the input with a
+ * given string.
+ *
+ * @param replacement
+ * the replacement text.
+ * @return the modified input string.
+ */
+ public String replaceAll(String replacement) {
+ StringBuffer buffer = new StringBuffer(input.length());
+
+ findPos = 0;
+ appendPos = 0;
+ matchFound = false;
+ searching = false;
+
+ while (find()) {
+ appendReplacement(buffer, replacement);
+ }
+
+ return appendTail(buffer).toString();
+ }
+
+ /**
+ * Returns the {@link Pattern} instance used inside this matcher.
+ *
+ * @return the {@code Pattern} instance.
+ */
+ public Pattern pattern() {
+ return pattern;
+ }
+
+ /**
+ * Returns the text that matched a given group of the regular expression.
+ *
+ * @param group
+ * the group, ranging from 0 to groupCount() - 1, with 0
+ * representing the whole pattern.
+ * @return the text that matched the group.
+ * @throws IllegalStateException
+ * if no successful match has been made.
+ */
+ public String group(int group) {
+ ensureMatch();
+ int from = matchOffsets[group * 2];
+ int to = matchOffsets[(group * 2) + 1];
+ if (from == -1 || to == -1) {
+ return null;
+ } else {
+ return input.substring(from, to);
}
}
-
+
+ /**
+ * Returns the text that matched the whole regular expression.
+ *
+ * @return the text.
+ * @throws IllegalStateException
+ * if no successful match has been made.
+ */
+ public String group() {
+ return group(0);
+ }
+
+ /**
+ * Returns the next occurrence of the {@link Pattern} in the input. The
+ * method starts the search from the given character in the input.
+ *
+ * @param start
+ * The index in the input at which the find operation is to
+ * begin. If this is less than the start of the region, it is
+ * automatically adjusted to that value. If it is beyond the end
+ * of the region, the method will fail.
+ * @return true if (and only if) a match has been found.
+ */
+ public boolean find(int start) {
+ findPos = start;
+
+ if (findPos < regionStart) {
+ findPos = regionStart;
+ } else if (findPos >= regionEnd) {
+ matchFound = false;
+ return false;
+ }
+
+ matchFound = NativeRegEx.find(nativePattern, findPos);
+ if (matchFound) {
+ NativeRegEx.startEnd(nativePattern, matchOffsets);
+ findPos = matchOffsets[1];
+ }
+
+ return matchFound;
+ }
+
/**
* Returns the next occurrence of the {@link Pattern} in the input. If a
* previous match was successful, the method continues the search from the
@@ -389,7 +425,6 @@
* either from the region start (if one has been set), or from position 0.
*
* @return true if (and only if) a match has been found.
- * @since Android 1.0
*/
public boolean find() {
if (!searching) {
@@ -408,34 +443,35 @@
}
/**
- * Returns the next occurrence of the {@link Pattern} in the input. The
- * method starts the search from the given character in the input.
- *
- * @param start
- * The index in the input at which the find operation is to
- * begin. If this is less than the start of the region, it is
- * automatically adjusted to that value. If it is beyond the end
- * of the region, the method will fail.
- * @return true if (and only if) a match has been found.
- * @since Android 1.0
+ * Returns the index of the first character of the text that matched a given
+ * group.
+ *
+ * @param group
+ * the group, ranging from 0 to groupCount() - 1, with 0
+ * representing the whole pattern.
+ * @return the character index.
+ * @throws IllegalStateException
+ * if no successful match has been made.
*/
- public boolean find(int start) {
- findPos = start;
-
- if (findPos < regionStart) {
- findPos = regionStart;
- } else if (findPos >= regionEnd) {
- matchFound = false;
- return false;
- }
-
- matchFound = NativeRegEx.find(nativePattern, findPos);
- if (matchFound) {
- NativeRegEx.startEnd(nativePattern, matchOffsets);
- findPos = matchOffsets[1];
- }
-
- return matchFound;
+ public int start(int group) throws IllegalStateException {
+ ensureMatch();
+ return matchOffsets[group * 2];
+ }
+
+ /**
+ * Returns the index of the first character following the text that matched
+ * a given group.
+ *
+ * @param group
+ * the group, ranging from 0 to groupCount() - 1, with 0
+ * representing the whole pattern.
+ * @return the character index.
+ * @throws IllegalStateException
+ * if no successful match has been made.
+ */
+ public int end(int group) {
+ ensureMatch();
+ return matchOffsets[(group * 2) + 1];
}
/**
@@ -444,8 +480,6 @@
*
* @return true if (and only if) the {@code Pattern} matches the entire
* region.
- *
- * @since Android 1.0
*/
public boolean matches() {
matchFound = NativeRegEx.matches(nativePattern, -1);
@@ -458,13 +492,34 @@
}
/**
+ * Returns a replacement string for the given one that has all backslashes
+ * and dollar signs escaped.
+ *
+ * @param s
+ * the input string.
+ * @return the input string, with all backslashes and dollar signs having
+ * been escaped.
+ */
+ public static String quoteReplacement(String s) {
+ StringBuffer buffer = new StringBuffer(s.length());
+
+ for (int i = 0; i < s.length(); i++) {
+ char c = s.charAt(i);
+ if (c == '\\' || c == '$') {
+ buffer.append('\\');
+ }
+ buffer.append(c);
+ }
+
+ return buffer.toString();
+ }
+
+ /**
* Tries to match the {@link Pattern}, starting from the beginning of the
* region (or the beginning of the input, if no region has been set).
* Doesn't require the {@code Pattern} to match against the whole region.
*
* @return true if (and only if) the {@code Pattern} matches.
- *
- * @since Android 1.0
*/
public boolean lookingAt() {
matchFound = NativeRegEx.lookingAt(nativePattern, -1);
@@ -483,27 +538,19 @@
* @return the character index.
* @throws IllegalStateException
* if no successful match has been made.
- * @since Android 1.0
*/
- public int start() throws IllegalStateException {
+ public int start() {
return start(0);
}
/**
- * Returns the index of the first character of the text that matched a given
- * group.
- *
- * @param group
- * the group, ranging from 0 to groupCount() - 1, with 0
- * representing the whole pattern.
- * @return the character index.
- * @throws IllegalStateException
- * if no successful match has been made.
- * @since Android 1.0
+ * Returns the number of groups in the results, which is always equal to
+ * the number of groups in the original regular expression.
+ *
+ * @return the number of groups.
*/
- public int start(int group) throws IllegalStateException {
- ensureMatch();
- return matchOffsets[group * 2];
+ public int groupCount() {
+ return pattern.mGroupCount;
}
/**
@@ -513,94 +560,19 @@
* @return the character index.
* @throws IllegalStateException
* if no successful match has been made.
- * @since Android 1.0
*/
public int end() {
return end(0);
}
/**
- * Returns the index of the first character following the text that matched
- * a given group.
- *
- * @param group
- * the group, ranging from 0 to groupCount() - 1, with 0
- * representing the whole pattern.
- * @return the character index.
- * @throws IllegalStateException
- * if no successful match has been made.
- * @since Android 1.0
- */
- public int end(int group) {
- ensureMatch();
- return matchOffsets[(group * 2) + 1];
- }
-
- /**
- * Returns the text that matched the whole regular expression.
- *
- * @return the text.
- * @throws IllegalStateException
- * if no successful match has been made.
- * @since Android 1.0
- */
- public String group() {
- return group(0);
- }
-
- /**
- * Returns the text that matched a given group of the regular expression.
- *
- * @param group
- * the group, ranging from 0 to groupCount() - 1, with 0
- * representing the whole pattern.
- * @return the text that matched the group.
- * @throws IllegalStateException
- * if no successful match has been made.
- * @since Android 1.0
- */
- public String group(int group) {
- ensureMatch();
- int from = matchOffsets[group * 2];
- int to = matchOffsets[(group * 2) + 1];
- if (from == -1 || to == -1) {
- return null;
- } else {
- return input.substring(from, to);
- }
- }
-
- /**
- * Indicates whether the last match hit the end of the input.
- *
- * @return true if (and only if) the last match hit the end of the input.
- * @since Android 1.0
- */
- public boolean hitEnd() {
- return NativeRegEx.hitEnd(nativePattern);
- }
-
- /**
- * Indicates whether more input might change a successful match into an
- * unsuccessful one.
- *
- * @return true if (and only if) more input might change a successful match
- * into an unsuccessful one.
- * @since Android 1.0
- */
- public boolean requireEnd() {
- return NativeRegEx.requireEnd(nativePattern);
- }
-
- /**
* Converts the current match into a separate {@link MatchResult} instance
* that is independent from this matcher. The new object is unaffected when
* the state of this matcher changes.
- *
+ *
* @return the new {@code MatchResult}.
* @throws IllegalStateException
* if no successful match has been made.
- * @since Android 1.0
*/
public MatchResult toMatchResult() {
ensureMatch();
@@ -608,160 +580,146 @@
}
/**
- * Appends a literal part of the input plus a replacement for the current
- * match to a given {@link StringBuffer}. The literal part is exactly the
- * part of the input between the previous match and the current match. The
- * method can be used in conjunction with {@link #find()} and
- * {@link #appendTail(StringBuffer)} to walk through the input and replace
- * all occurrences of the {@code Pattern} with something else.
- *
- * @param buffer
- * the {@code StringBuffer} to append to.
- * @param replacement
- * the replacement text.
+ * Determines whether this matcher has anchoring bounds enabled or not. When
+ * anchoring bounds are enabled, the start and end of the input match the
+ * '^' and '$' meta-characters, otherwise not. Anchoring bounds are enabled
+ * by default.
+ *
+ * @param value
+ * the new value for anchoring bounds.
* @return the {@code Matcher} itself.
- * @throws IllegalStateException
- * if no successful match has been made.
- * @since Android 1.0
*/
- public Matcher appendReplacement(StringBuffer buffer, String replacement)
- throws IllegalStateException {
-
- buffer.append(input.substring(appendPos, start()));
- appendEvaluated(buffer, replacement);
- appendPos = end();
-
+ public Matcher useAnchoringBounds(boolean value) {
+ anchoringBounds = value;
+ NativeRegEx.useAnchoringBounds(nativePattern, value);
return this;
}
/**
- * Appends the (unmatched) remainder of the input to the given
- * {@link StringBuffer}. The method can be used in conjunction with
- * {@link #find()} and {@link #appendReplacement(StringBuffer, String)} to
- * walk through the input and replace all matches of the {@code Pattern}
- * with something else.
- *
- * @param buffer
- * the {@code StringBuffer} to append to.
- * @return the {@code StringBuffer}.
+ * Indicates whether this matcher has anchoring bounds enabled. When
+ * anchoring bounds are enabled, the start and end of the input match the
+ * '^' and '$' meta-characters, otherwise not. Anchoring bounds are enabled
+ * by default.
+ *
+ * @return true if (and only if) the {@code Matcher} uses anchoring bounds.
+ */
+ public boolean hasAnchoringBounds() {
+ return anchoringBounds;
+ }
+
+ /**
+ * Determines whether this matcher has transparent bounds enabled or not.
+ * When transparent bounds are enabled, the parts of the input outside the
+ * region are subject to lookahead and lookbehind, otherwise they are not.
+ * Transparent bounds are disabled by default.
+ *
+ * @param value
+ * the new value for transparent bounds.
+ * @return the {@code Matcher} itself.
+ */
+ public Matcher useTransparentBounds(boolean value) {
+ transparentBounds = value;
+ NativeRegEx.useTransparentBounds(nativePattern, value);
+ return this;
+ }
+
+ /**
+ * Makes sure that a successful match has been made. Is invoked internally
+ * from various places in the class.
+ *
* @throws IllegalStateException
* if no successful match has been made.
- * @since Android 1.0
*/
- public StringBuffer appendTail(StringBuffer buffer) {
- if (appendPos < regionEnd) {
- buffer.append(input.substring(appendPos, regionEnd));
+ private void ensureMatch() {
+ if (!matchFound) {
+ throw new IllegalStateException("No successful match so far");
}
-
- return buffer;
}
/**
- * Internal helper method to append a given string to a given string buffer.
- * If the string contains any references to groups, these are replaced by
- * the corresponding group's contents.
- *
- * @param buffer
- * the string buffer.
- * @param s
- * the string to append.
+ * Indicates whether this matcher has transparent bounds enabled. When
+ * transparent bounds are enabled, the parts of the input outside the region
+ * are subject to lookahead and lookbehind, otherwise they are not.
+ * Transparent bounds are disabled by default.
+ *
+ * @return true if (and only if) the {@code Matcher} uses anchoring bounds.
*/
- private void appendEvaluated(StringBuffer buffer, String s) {
- boolean escape = false;
- boolean dollar = false;
-
- for (int i = 0; i < s.length(); i++) {
- char c = s.charAt(i);
- if (c == '\\' && !escape) {
- escape = true;
- } else if (c == '$' && !escape) {
- dollar = true;
- } else if (c >= '0' && c <= '9' && dollar) {
- buffer.append(group(c - '0'));
- dollar = false;
- } else {
- buffer.append(c);
- dollar = false;
- escape = false;
- }
- }
-
- // This seemingly stupid piece of code reproduces a JDK bug.
- if (escape) {
- throw new ArrayIndexOutOfBoundsException(s.length());
- }
+ public boolean hasTransparentBounds() {
+ return transparentBounds;
}
-
+
/**
- * Replaces all occurrences of this matcher's pattern in the input with a
- * given string.
- *
- * @param replacement
- * the replacement text.
- * @return the modified input string.
- * @since Android 1.0
+ * Returns this matcher's region start, that is, the first character that is
+ * considered for a match.
+ *
+ * @return the start of the region.
*/
- public String replaceAll(String replacement) {
- StringBuffer buffer = new StringBuffer(input.length());
-
- findPos = 0;
- appendPos = 0;
+ public int regionStart() {
+ return regionStart;
+ }
+
+ /**
+ * Returns this matcher's region end, that is, the first character that is
+ * not considered for a match.
+ *
+ * @return the end of the region.
+ */
+ public int regionEnd() {
+ return regionEnd;
+ }
+
+ /**
+ * Indicates whether more input might change a successful match into an
+ * unsuccessful one.
+ *
+ * @return true if (and only if) more input might change a successful match
+ * into an unsuccessful one.
+ */
+ public boolean requireEnd() {
+ return NativeRegEx.requireEnd(nativePattern);
+ }
+
+ /**
+ * Indicates whether the last match hit the end of the input.
+ *
+ * @return true if (and only if) the last match hit the end of the input.
+ */
+ public boolean hitEnd() {
+ return NativeRegEx.hitEnd(nativePattern);
+ }
+
+ /**
+ * Sets a new pattern for the {@code Matcher}. Results of a previous find
+ * get lost. The next attempt to find an occurrence of the {@link Pattern}
+ * in the string will start at the beginning of the input.
+ *
+ * @param pattern
+ * the new {@code Pattern}.
+ *
+ * @return the {@code Matcher} itself.
+ */
+ public Matcher usePattern(Pattern pattern) {
+ if (pattern == null) {
+ throw new IllegalArgumentException();
+ }
+
+ this.pattern = pattern;
+
+ if (nativePattern != 0) {
+ NativeRegEx.close(nativePattern);
+ }
+ nativePattern = NativeRegEx.clone(pattern.mNativePattern);
+
+ if (input != null) {
+ NativeRegEx.setText(nativePattern, input);
+ NativeRegEx.setRegion(nativePattern, regionStart, regionEnd);
+ NativeRegEx.useAnchoringBounds(nativePattern, anchoringBounds);
+ NativeRegEx.useTransparentBounds(nativePattern, transparentBounds);
+ }
+
+ matchOffsets = new int[(this.pattern.mGroupCount + 1) * 2];
matchFound = false;
- searching = false;
-
- while (find()) {
- appendReplacement(buffer, replacement);
- }
-
- return appendTail(buffer).toString();
- }
-
- /**
- * Replaces the first occurrence of this matcher's pattern in the input with
- * a given string.
- *
- * @param replacement
- * the replacement text.
- * @return the modified input string.
- * @since Android 1.0
- */
- public String replaceFirst(String replacement) {
- StringBuffer buffer = new StringBuffer(input.length());
-
- findPos = 0;
- appendPos = 0;
- matchFound = false;
- searching = false;
-
- if (find()) {
- appendReplacement(buffer, replacement);
- }
-
- return appendTail(buffer).toString();
- }
-
- /**
- * Returns a replacement string for the given one that has all backslashes
- * and dollar signs escaped.
- *
- * @param s
- * the input string.
- * @return the input string, with all backslashes and dollar signs having
- * been escaped.
- * @since Android 1.0
- */
- public static String quoteReplacement(String s) {
- StringBuffer buffer = new StringBuffer(s.length());
-
- for (int i = 0; i < s.length(); i++) {
- char c = s.charAt(i);
- if (c == '\\' || c == '$') {
- buffer.append('\\');
- }
- buffer.append(c);
- }
-
- return buffer.toString();
+ return this;
}
@Override
diff --git a/libcore/regex/src/main/java/java/util/regex/Pattern.java b/libcore/regex/src/main/java/java/util/regex/Pattern.java
index 2c71de1..db3bc21 100644
--- a/libcore/regex/src/main/java/java/util/regex/Pattern.java
+++ b/libcore/regex/src/main/java/java/util/regex/Pattern.java
@@ -47,7 +47,7 @@
* boolean b2 = Pattern.matches("Hello, A[a-z]*!", "Hello, Robot!"); // false
* </pre>
* <p/>
- * Please consult the <a href="package-summary.html">package documentation</a> for an
+ * Please consult the <a href="package.html">package documentation</a> for an
* overview of the regular expression syntax used in this class as well as
* Android-specific implementation details.
*
@@ -61,8 +61,6 @@
/**
* This constant specifies that a pattern matches Unix line endings ('\n')
* only against the '.', '^', and '$' meta characters.
- *
- * @since Android 1.0
*/
public static final int UNIX_LINES = 0x01;
@@ -76,8 +74,6 @@
* constant. So if case insensitivity is enabled, this automatically extends
* to all Unicode characters. The {@code UNICODE_CASE} constant itself has
* no special consequences.
- *
- * @since Android 1.0
*/
public static final int CASE_INSENSITIVE = 0x02;
@@ -85,8 +81,6 @@
* This constant specifies that a {@code Pattern} may contain whitespace or
* comments. Otherwise comments and whitespace are taken as literal
* characters.
- *
- * @since Android 1.0
*/
public static final int COMMENTS = 0x04;
@@ -94,24 +88,18 @@
* This constant specifies that the meta characters '^' and '$' match only
* the beginning and end end of an input line, respectively. Normally, they
* match the beginning and the end of the complete input.
- *
- * @since Android 1.0
*/
public static final int MULTILINE = 0x08;
/**
* This constant specifies that the whole {@code Pattern} is to be taken
* literally, that is, all meta characters lose their meanings.
- *
- * @since Android 1.0
*/
public static final int LITERAL = 0x10;
/**
* This constant specifies that the '.' meta character matches arbitrary
* characters, including line endings, which is normally not the case.
- *
- * @since Android 1.0
*/
public static final int DOTALL = 0x20;
@@ -126,8 +114,6 @@
* constant. So if case insensitivity is enabled, this automatically extends
* to all Unicode characters. The {@code UNICODE_CASE} constant then has no
* special consequences.
- *
- * @since Android 1.0
*/
public static final int UNICODE_CASE = 0x40;
@@ -135,8 +121,6 @@
* This constant specifies that a character in a {@code Pattern} and a
* character in the input string only match if they are canonically
* equivalent. It is (currently) not supported in Android.
- *
- * @since Android 1.0
*/
public static final int CANON_EQ = 0x80;
@@ -159,24 +143,144 @@
* Holds the number of groups in the pattern.
*/
transient int mGroupCount;
-
+
+
/**
- * Compiles a regular expression, creating a new Pattern instance in the
- * process. This is actually a convenience method that calls {@link
- * #compile(String, int)} with a {@code flags} value of zero.
- *
- * @param pattern
- * the regular expression.
- *
- * @return the new {@code Pattern} instance.
- *
- * @throws PatternSyntaxException
- * if the regular expression is syntactically incorrect.
- *
- * @since Android 1.0
+ * Returns a {@link Matcher} for the {@code Pattern} and a given input. The
+ * {@code Matcher} can be used to match the {@code Pattern} against the
+ * whole input, find occurrences of the {@code Pattern} in the input, or
+ * replace parts of the input.
+ *
+ * @param input
+ * the input to process.
+ *
+ * @return the resulting {@code Matcher}.
*/
- public static Pattern compile(String pattern) throws PatternSyntaxException {
- return new Pattern(pattern, 0);
+ public Matcher matcher(CharSequence input) {
+ return new Matcher(this, input);
+ }
+
+ /**
+ * Splits the given input sequence at occurrences of this {@code Pattern}.
+ *
+ * <p>If this {@code Pattern} does not occur in the input, the result is an
+ * array containing the input (converted from a {@code CharSequence} to
+ * a {@code String}).
+ *
+ * <p>Otherwise, the {@code limit} parameter controls the contents of the
+ * returned array as described below.
+ *
+ * @param inputSeq
+ * the input sequence.
+ * @param limit
+ * Determines the maximum number of entries in the resulting
+ * array, and the treatment of trailing empty strings.
+ * <ul>
+ * <li>For n > 0, the resulting array contains at most n
+ * entries. If this is fewer than the number of matches, the
+ * final entry will contain all remaining input.
+ * <li>For n < 0, the length of the resulting array is
+ * exactly the number of occurrences of the {@code Pattern}
+ * plus one for the text after the final separator.
+ * All entries are included.
+ * <li>For n == 0, the result is as for n < 0, except
+ * trailing empty strings will not be returned. (Note that
+ * the case where the input is itself an empty string is
+ * special, as described above, and the limit parameter does
+ * not apply there.)
+ * </ul>
+ *
+ * @return the resulting array.
+ */
+ public String[] split(CharSequence inputSeq, int limit) {
+ if (inputSeq.length() == 0) {
+ // Unlike Perl, which considers the result of splitting the empty
+ // string to be the empty array, Java returns an array containing
+ // the empty string.
+ return new String[] { "" };
+ }
+
+ int maxLength = limit <= 0 ? Integer.MAX_VALUE : limit;
+
+ String input = inputSeq.toString();
+ ArrayList<String> list = new ArrayList<String>();
+
+ Matcher matcher = new Matcher(this, inputSeq);
+ int savedPos = 0;
+
+ // Add text preceding each occurrence, if enough space.
+ while(matcher.find() && list.size() + 1 < maxLength) {
+ list.add(input.substring(savedPos, matcher.start()));
+ savedPos = matcher.end();
+ }
+
+ // Add trailing text if enough space.
+ if (list.size() < maxLength) {
+ if (savedPos < input.length()) {
+ list.add(input.substring(savedPos));
+ } else {
+ list.add("");
+ }
+ }
+
+ // Remove trailing empty matches in the limit == 0 case.
+ if (limit == 0) {
+ int i = list.size() - 1;
+ while (i >= 0 && "".equals(list.get(i))) {
+ list.remove(i);
+ i--;
+ }
+ }
+
+ return list.toArray(new String[list.size()]);
+ }
+
+ /**
+ * Splits a given input around occurrences of a regular expression. This is
+ * a convenience method that is equivalent to calling the method
+ * {@link #split(java.lang.CharSequence, int)} with a limit of 0.
+ *
+ * @param input
+ * the input sequence.
+ *
+ * @return the resulting array.
+ */
+ public String[] split(CharSequence input) {
+ return split(input, 0);
+ }
+
+ /**
+ * Returns the regular expression that was compiled into this
+ * {@code Pattern}.
+ *
+ * @return the regular expression.
+ */
+ public String pattern() {
+ return pattern;
+ }
+
+ @Override
+ public String toString() {
+ return pattern;
+ }
+
+ /**
+ * Returns the flags that have been set for this {@code Pattern}.
+ *
+ * @return the flags that have been set. A combination of the constants
+ * defined in this class.
+ *
+ * @see #CANON_EQ
+ * @see #CASE_INSENSITIVE
+ * @see #COMMENTS
+ * @see #DOTALL
+ * @see #LITERAL
+ * @see #MULTILINE
+ * @see #UNICODE_CASE
+ * @see #UNIX_LINES
+ */
+ public int flags() {
+ return flags;
}
/**
@@ -208,8 +312,6 @@
* @see #MULTILINE
* @see #UNICODE_CASE
* @see #UNIX_LINES
- *
- * @since Android 1.0
*/
public static Pattern compile(String pattern, int flags) throws PatternSyntaxException {
return new Pattern(pattern, flags);
@@ -238,7 +340,24 @@
compileImpl(pattern, flags);
}
-
+
+ /**
+ * Compiles a regular expression, creating a new Pattern instance in the
+ * process. This is actually a convenience method that calls {@link
+ * #compile(String, int)} with a {@code flags} value of zero.
+ *
+ * @param pattern
+ * the regular expression.
+ *
+ * @return the new {@code Pattern} instance.
+ *
+ * @throws PatternSyntaxException
+ * if the regular expression is syntactically incorrect.
+ */
+ public static Pattern compile(String pattern) {
+ return new Pattern(pattern, 0);
+ }
+
/**
* Compiles the given regular expression using the given flags. Used
* internally only.
@@ -266,56 +385,6 @@
}
/**
- * Returns the regular expression that was compiled into this
- * {@code Pattern}.
- *
- * @return the regular expression.
- *
- * @since Android 1.0
- */
- public String pattern() {
- return pattern;
- }
-
- /**
- * Returns the flags that have been set for this {@code Pattern}.
- *
- * @return the flags that have been set. A combination of the constants
- * defined in this class.
- *
- * @see #CANON_EQ
- * @see #CASE_INSENSITIVE
- * @see #COMMENTS
- * @see #DOTALL
- * @see #LITERAL
- * @see #MULTILINE
- * @see #UNICODE_CASE
- * @see #UNIX_LINES
- *
- * @since Android 1.0
- */
- public int flags() {
- return flags;
- }
-
- /**
- * Returns a {@link Matcher} for the {@code Pattern} and a given input. The
- * {@code Matcher} can be used to match the {@code Pattern} against the
- * whole input, find occurrences of the {@code Pattern} in the input, or
- * replace parts of the input.
- *
- * @param input
- * the input to process.
- *
- * @return the resulting {@code Matcher}.
- *
- * @since Android 1.0
- */
- public Matcher matcher(CharSequence input) {
- return new Matcher(this, input);
- }
-
- /**
* Tries to match a given regular expression against a given input. This is
* actually nothing but a convenience method that compiles the regular
* expression into a {@code Pattern}, builds a {@link Matcher} for it, and
@@ -332,107 +401,12 @@
*
* @see Pattern#compile(java.lang.String, int)
* @see Matcher#matches()
- *
- * @since Android 1.0
*/
- static public boolean matches(String regex, CharSequence input) {
+ public static boolean matches(String regex, CharSequence input) {
return new Matcher(new Pattern(regex, 0), input).matches();
}
/**
- * Splits a given input around occurrences of a regular expression. This is
- * a convenience method that is equivalent to calling the method
- * {@link #split(java.lang.CharSequence, int)} with a limit of 0.
- *
- * @param input
- * the input sequence.
- *
- * @return the resulting array.
- *
- * @since Android 1.0
- */
- public String[] split(CharSequence input) {
- return split(input, 0);
- }
-
- /**
- * Splits the given input sequence at occurrences of this {@code Pattern}.
- *
- * If this {@code Pattern} does not occur in the input, the result is an
- * array containing the input (converted from a {@code CharSequence} to
- * a {@code String}).
- *
- * Otherwise, the {@code limit} parameter controls the contents of the
- * returned array as described below.
- *
- * @param inputSeq
- * the input sequence.
- * @param limit
- * Determines the maximum number of entries in the resulting
- * array, and the treatment of trailing empty strings.
- * <ul>
- * <li>For n > 0, the resulting array contains at most n
- * entries. If this is fewer than the number of matches, the
- * final entry will contain all remaining input.
- * <li>For n < 0, the length of the resulting array is
- * exactly the number of occurrences of the {@code Pattern}
- * plus one for the text after the final separator.
- * All entries are included.
- * <li>For n == 0, the result is as for n < 0, except
- * trailing empty strings will not be returned. (Note that
- * the case where the input is itself an empty string is
- * special, as described above, and the limit parameter does
- * not apply there.)
- * </ul>
- *
- * @return the resulting array.
- *
- * @since Android 1.0
- */
- public String[] split(CharSequence inputSeq, int limit) {
- if (inputSeq.length() == 0) {
- // Unlike Perl, which considers the result of splitting the empty
- // string to be the empty array, Java returns an array containing
- // the empty string.
- return new String[] { "" };
- }
-
- int maxLength = limit <= 0 ? Integer.MAX_VALUE : limit;
-
- String input = inputSeq.toString();
- ArrayList<String> list = new ArrayList<String>();
-
- Matcher matcher = new Matcher(this, inputSeq);
- int savedPos = 0;
-
- // Add text preceding each occurrence, if enough space.
- while(matcher.find() && list.size() + 1 < maxLength) {
- list.add(input.substring(savedPos, matcher.start()));
- savedPos = matcher.end();
- }
-
- // Add trailing text if enough space.
- if (list.size() < maxLength) {
- if (savedPos < input.length()) {
- list.add(input.substring(savedPos));
- } else {
- list.add("");
- }
- }
-
- // Remove trailing empty matches in the limit == 0 case.
- if (limit == 0) {
- int i = list.size() - 1;
- while (i >= 0 && "".equals(list.get(i))) {
- list.remove(i);
- i--;
- }
- }
-
- return list.toArray(new String[list.size()]);
- }
-
- /**
* Quotes a given string using "\Q" and "\E", so that all other
* meta-characters lose their special meaning. If the string is used for a
* {@code Pattern} afterwards, it can only be matched literally.
@@ -441,27 +415,20 @@
* the string to quote.
*
* @return the quoted string.
- *
- * @since Android 1.0
*/
public static String quote(String s) {
- StringBuffer sb = new StringBuffer().append("\\Q");
+ StringBuilder sb = new StringBuilder().append("\\Q"); //$NON-NLS-1$
int apos = 0;
int k;
- while ((k = s.indexOf("\\E", apos)) >= 0) {
- sb.append(s.substring(apos, k + 2)).append("\\\\E\\Q");
+ while ((k = s.indexOf("\\E", apos)) >= 0) { //$NON-NLS-1$
+ sb.append(s.substring(apos, k + 2)).append("\\\\E\\Q"); //$NON-NLS-1$
apos = k + 2;
}
- return sb.append(s.substring(apos)).append("\\E").toString();
+ return sb.append(s.substring(apos)).append("\\E").toString(); //$NON-NLS-1$
}
@Override
- public String toString() {
- return pattern;
- }
-
- @Override
protected void finalize() throws Throwable {
try {
if (mNativePattern != 0) {
@@ -474,7 +441,7 @@
}
/**
- * Provides serialization support
+ * Serialization support
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
diff --git a/libcore/regex/src/main/java/java/util/regex/PatternSyntaxException.java b/libcore/regex/src/main/java/java/util/regex/PatternSyntaxException.java
index e4d5abd..d59bdd4 100644
--- a/libcore/regex/src/main/java/java/util/regex/PatternSyntaxException.java
+++ b/libcore/regex/src/main/java/java/util/regex/PatternSyntaxException.java
@@ -1,17 +1,18 @@
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
*
- * 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
*
- * 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.
+ * 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 java.util.regex;
@@ -25,24 +26,22 @@
*
* @see Pattern#compile(String)
* @see Pattern#compile(java.lang.String,int)
- *
- * @since Android 1.0
*/
public class PatternSyntaxException extends IllegalArgumentException {
private static final long serialVersionUID = -3864639126226059218L;
-
- /**
- * Holds the syntactically incorrect regular expression, or null if the
- * regular expression is not known.
- */
- private String pattern;
/**
* Holds the description of the syntax error, or null if the description is
* not known.
*/
- private String description;
+ private String desc;
+
+ /**
+ * Holds the syntactically incorrect regular expression, or null if the
+ * regular expression is not known.
+ */
+ private String pattern;
/**
* Holds the index around which the error occured, or -1, in case it is
@@ -63,11 +62,10 @@
* @param index
* the character index around which the error occurred, or -1 if
* the index is not known.
- * @since Android 1.0
*/
public PatternSyntaxException(String description, String pattern, int index) {
+ this.desc = description;
this.pattern = pattern;
- this.description = description;
this.index = index;
}
@@ -76,7 +74,6 @@
*
* @return the regular expression.
*
- * @since Android 1.0
*/
public String getPattern() {
return pattern;
@@ -88,16 +85,15 @@
* original regular expression, and the index at which the error occured.
*
* @return the error message.
- *
- * @since Android 1.0
*/
@Override
public String getMessage() {
+ // BEGIN android-changed
StringBuilder builder = new StringBuilder("Syntax error");
- if (description != null) {
+ if (desc != null) {
builder.append(' ');
- builder.append(description);
+ builder.append(desc);
}
if (index >= 0) {
@@ -118,6 +114,7 @@
}
return builder.toString();
+ // END android-changed
}
/**
@@ -125,10 +122,9 @@
* description is not known.
*
* @return the description.
- * @since Android 1.0
*/
public String getDescription() {
- return description;
+ return desc;
}
/**
@@ -137,10 +133,8 @@
*
* @return the index.
*
- * @since Android 1.0
*/
public int getIndex() {
return index;
}
-
}
diff --git a/libcore/security/src/main/java/java/security/AccessControlException.java b/libcore/security/src/main/java/java/security/AccessControlException.java
index 1710e77..ae23ab1 100644
--- a/libcore/security/src/main/java/java/security/AccessControlException.java
+++ b/libcore/security/src/main/java/java/security/AccessControlException.java
@@ -15,18 +15,11 @@
* limitations under the License.
*/
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision$
-*/
-
package java.security;
/**
* {@code AccessControlException} is thrown if the access control infrastructure
* denies protected access due to missing permissions.
- *
- * @since Android 1.0
*/
public class AccessControlException extends SecurityException {
@@ -37,10 +30,9 @@
/**
* Constructs a new instance of {@code AccessControlException} with the
* given message.
- *
+ *
* @param message
* the detail message for this exception.
- * @since Android 1.0
*/
public AccessControlException(String message) {
super(message);
@@ -49,12 +41,11 @@
/**
* Constructs a new instance of {@code AccessControlException} with the
* given message and the requested {@code Permission} which was not granted.
- *
+ *
* @param message
* the detail message for the exception.
* @param perm
* the requested {@code Permission} which was not granted.
- * @since Android 1.0
*/
public AccessControlException(String message, Permission perm) {
super(message);
@@ -64,9 +55,8 @@
/**
* Returns the requested permission that caused this Exception or {@code
* null} if there is no corresponding {@code Permission}.
- *
+ *
* @return the requested permission that caused this Exception, maybe {@code null}.
- * @since Android 1.0
*/
public Permission getPermission() {
return perm;
diff --git a/libcore/security/src/main/java/java/security/AlgorithmParameterGenerator.java b/libcore/security/src/main/java/java/security/AlgorithmParameterGenerator.java
index 199efa1..6814813 100644
--- a/libcore/security/src/main/java/java/security/AlgorithmParameterGenerator.java
+++ b/libcore/security/src/main/java/java/security/AlgorithmParameterGenerator.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
package java.security;
import java.security.spec.AlgorithmParameterSpec;
@@ -30,8 +25,6 @@
/**
* {@code AlgorithmParameterGenerator} is an engine class which is capable of
* generating parameters for the algorithm it was initialized with.
- *
- * @since Android 1.0
*/
public class AlgorithmParameterGenerator {
@@ -56,14 +49,13 @@
/**
* Constructs a new instance of {@code AlgorithmParameterGenerator} with the
* given arguments.
- *
+ *
* @param paramGenSpi
* a concrete implementation, this engine instance delegates to.
* @param provider
* the provider.
* @param algorithm
* the name of the algorithm.
- * @since Android 1.0
*/
protected AlgorithmParameterGenerator(
AlgorithmParameterGeneratorSpi paramGenSpi, Provider provider,
@@ -75,9 +67,8 @@
/**
* Returns the name of the algorithm.
- *
+ *
* @return the name of the algorithm.
- * @since Android 1.0
*/
public final String getAlgorithm() {
return algorithm;
@@ -95,7 +86,6 @@
* if the specified algorithm is not available.
* @throws NullPointerException
* if {@code algorithm} is {@code null}.
- * @since Android 1.0
*/
public static AlgorithmParameterGenerator getInstance(String algorithm)
throws NoSuchAlgorithmException {
@@ -127,7 +117,6 @@
* if the specified provider is not available.
* @throws NullPointerException
* if {@code algorithm} is {@code null}.
- * @since Android 1.0
*/
public static AlgorithmParameterGenerator getInstance(String algorithm,
String provider) throws NoSuchAlgorithmException,
@@ -157,7 +146,6 @@
* if the specified algorithm is not available.
* @throws NullPointerException
* if {@code algorithm} is {@code null}.
- * @since Android 1.0
*/
public static AlgorithmParameterGenerator getInstance(String algorithm,
Provider provider) throws NoSuchAlgorithmException {
@@ -178,10 +166,9 @@
/**
* Returns the provider associated with this {@code
* AlgorithmParameterGenerator}.
- *
+ *
* @return the provider associated with this {@code
* AlgorithmParameterGenerator}.
- * @since Android 1.0
*/
public final Provider getProvider() {
return provider;
@@ -191,10 +178,9 @@
* Initializes this {@code AlgorithmParameterGenerator} with the given size.
* The default parameter set and a default {@code SecureRandom} instance
* will be used.
- *
+ *
* @param size
* the size (in number of bits).
- * @since Android 1.0
*/
public final void init(int size) {
spiImpl.engineInit(size, randm);
@@ -204,12 +190,11 @@
* Initializes this {@code AlgorithmParameterGenerator} with the given size
* and the given {@code SecureRandom}. The default parameter set will be
* used.
- *
+ *
* @param size
* the size (in number of bits).
* @param random
* the source of randomness.
- * @since Android 1.0
*/
public final void init(int size, SecureRandom random) {
spiImpl.engineInit(size, random);
@@ -219,12 +204,11 @@
* Initializes this {@code AlgorithmParameterGenerator} with the given {@code
* AlgorithmParameterSpec}. A default {@code SecureRandom} instance will be
* used.
- *
+ *
* @param genParamSpec
* the parameters to use.
* @throws InvalidAlgorithmParameterException
* if the specified parameters are not supported.
- * @since Android 1.0
*/
public final void init(AlgorithmParameterSpec genParamSpec)
throws InvalidAlgorithmParameterException {
@@ -234,14 +218,13 @@
/**
* Initializes this {@code AlgorithmParameterGenerator} with the given
* {@code AlgorithmParameterSpec} and the given {@code SecureRandom}.
- *
+ *
* @param genParamSpec
* the parameters to use.
* @param random
* the source of randomness.
* @throws InvalidAlgorithmParameterException
* if the specified parameters are not supported.
- * @since Android 1.0
*/
public final void init(AlgorithmParameterSpec genParamSpec,
SecureRandom random) throws InvalidAlgorithmParameterException {
@@ -251,11 +234,10 @@
/**
* Computes and returns {@code AlgorithmParameters} for this generator's
* algorithm.
- *
+ *
* @return {@code AlgorithmParameters} for this generator's algorithm.
- * @since Android 1.0
*/
public final AlgorithmParameters generateParameters() {
return spiImpl.engineGenerateParameters();
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/AlgorithmParameterGeneratorSpi.java b/libcore/security/src/main/java/java/security/AlgorithmParameterGeneratorSpi.java
index 9ddff23..44b3def 100644
--- a/libcore/security/src/main/java/java/security/AlgorithmParameterGeneratorSpi.java
+++ b/libcore/security/src/main/java/java/security/AlgorithmParameterGeneratorSpi.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
package java.security;
import java.security.spec.AlgorithmParameterSpec;
@@ -29,14 +24,11 @@
* (SPI) definition for {@code AlgorithmParameterGenerator}.
*
* @see AlgorithmParameterGenerator
- * @since Android 1.0
*/
public abstract class AlgorithmParameterGeneratorSpi {
/**
* Constructs a new instance of {@code AlgorithmParameterGeneratorSpi} .
- *
- * @since Android 1.0
*/
public AlgorithmParameterGeneratorSpi() {
}
@@ -45,26 +37,24 @@
* Initializes this {@code AlgorithmParameterGeneratorSpi} with the given
* size and the given {@code SecureRandom}. The default parameter set
* will be used.
- *
+ *
* @param size
* the size (in number of bits).
* @param random
* the source of randomness.
- * @since Android 1.0
*/
protected abstract void engineInit(int size, SecureRandom random);
/**
* Initializes this {@code AlgorithmParameterGeneratorSpi} with the given
* {@code AlgorithmParameterSpec} and the given {@code SecureRandom}.
- *
+ *
* @param genParamSpec
* the parameters to use.
* @param random
* the source of randomness.
* @throws InvalidAlgorithmParameterException
* if the specified parameters are not supported.
- * @since Android 1.0
*/
protected abstract void engineInit(AlgorithmParameterSpec genParamSpec,
SecureRandom random) throws InvalidAlgorithmParameterException;
@@ -72,9 +62,8 @@
/**
* Computes and returns {@code AlgorithmParameters} for this generator's
* algorithm.
- *
+ *
* @return {@code AlgorithmParameters} for this generator's algorithm.
- * @since Android 1.0
*/
protected abstract AlgorithmParameters engineGenerateParameters();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/AlgorithmParameters.java b/libcore/security/src/main/java/java/security/AlgorithmParameters.java
index aaefe1b..d659200 100644
--- a/libcore/security/src/main/java/java/security/AlgorithmParameters.java
+++ b/libcore/security/src/main/java/java/security/AlgorithmParameters.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
package java.security;
import java.io.IOException;
@@ -33,8 +28,6 @@
/**
* {@code AlgorithmParameters} is an engine class which provides algorithm
* parameters.
- *
- * @since Android 1.0
*/
public class AlgorithmParameters {
/**
@@ -70,20 +63,16 @@
/**
* Constructs a new instance of {@code AlgorithmParameters} with the given
* arguments.
- *
+ *
* @param algPramSpi
* the concrete implementation.
* @param provider
* the security provider.
* @param algorithm
* the name of the algorithm.
- * @since Android 1.0
*/
protected AlgorithmParameters(AlgorithmParametersSpi algPramSpi,
Provider provider, String algorithm) {
- // BEGIN android-note
- // renamed parameter
- // END android-note
this.provider = provider;
this.algorithm = algorithm;
this.spiImpl = algPramSpi;
@@ -92,7 +81,7 @@
/**
* Returns a new instance of {@code AlgorithmParameters} for the specified
* algorithm.
- *
+ *
* @param algorithm
* the name of the algorithm to use.
* @return a new instance of {@code AlgorithmParameters} for the specified
@@ -101,7 +90,6 @@
* if the specified algorithm is not available.
* @throws NullPointerException
* if {@code algorithm} is {@code null}.
- * @since Android 1.0
*/
public static AlgorithmParameters getInstance(String algorithm)
throws NoSuchAlgorithmException {
@@ -118,7 +106,7 @@
/**
* Returns a new instance of {@code AlgorithmParameters} from the specified
* provider for the specified algorithm.
- *
+ *
* @param algorithm
* the name of the algorithm to use.
* @param provider
@@ -133,7 +121,6 @@
* if {@code provider} is {@code null} or of length zero.
* @throws NullPointerException
* if {@code algorithm} is {@code null}.
- * @since Android 1.0
*/
public static AlgorithmParameters getInstance(String algorithm,
String provider) throws NoSuchAlgorithmException,
@@ -152,7 +139,7 @@
/**
* Returns a new instance of {@code AlgorithmParameters} from the specified
* provider for the specified algorithm.
- *
+ *
* @param algorithm
* the name of the algorithm to use.
* @param provider
@@ -165,7 +152,6 @@
* if {@code algorithm} is {@code null}.
* @throws IllegalArgumentException
* if {@code provider} is {@code null}.
- * @since Android 1.0
*/
public static AlgorithmParameters getInstance(String algorithm,
Provider provider) throws NoSuchAlgorithmException {
@@ -184,9 +170,8 @@
/**
* Returns the provider associated with this {@code AlgorithmParameters}.
- *
+ *
* @return the provider associated with this {@code AlgorithmParameters}.
- * @since Android 1.0
*/
public final Provider getProvider() {
return provider;
@@ -194,9 +179,8 @@
/**
* Returns the name of the algorithm.
- *
+ *
* @return the name of the algorithm.
- * @since Android 1.0
*/
public final String getAlgorithm() {
return algorithm;
@@ -205,14 +189,13 @@
/**
* Initializes this {@code AlgorithmParameters} with the specified {@code
* AlgorithmParameterSpec}.
- *
+ *
* @param paramSpec
* the parameter specification.
* @throws InvalidParameterSpecException
* if this {@code AlgorithmParameters} has already been
* initialized or the given {@code paramSpec} is not appropriate
* for initializing this {@code AlgorithmParameters}.
- * @since Android 1.0
*/
public final void init(AlgorithmParameterSpec paramSpec)
throws InvalidParameterSpecException {
@@ -228,13 +211,12 @@
* Initializes this {@code AlgorithmParameters} with the specified {@code
* byte[]} using the default decoding format for parameters. The default
* encoding format is ASN.1.
- *
+ *
* @param params
* the encoded parameters.
* @throws IOException
* if this {@code AlgorithmParameters} has already been
* initialized, or the parameter could not be encoded.
- * @since Android 1.0
*/
public final void init(byte[] params) throws IOException {
if (initialized) {
@@ -247,7 +229,7 @@
/**
* Initializes this {@code AlgorithmParameters} with the specified {@code
* byte[]} using the specified decoding format.
- *
+ *
* @param params
* the encoded parameters.
* @param format
@@ -255,7 +237,6 @@
* @throws IOException
* if this {@code AlgorithmParameters} has already been
* initialized, or the parameter could not be encoded.
- * @since Android 1.0
*/
public final void init(byte[] params, String format) throws IOException {
if (initialized) {
@@ -268,7 +249,7 @@
/**
* Returns the {@code AlgorithmParameterSpec} for this {@code
* AlgorithmParameters}.
- *
+ *
* @param paramSpec
* the type of the parameter specification in which this
* parameters should be converted.
@@ -278,7 +259,6 @@
* if this {@code AlgorithmParameters} has already been
* initialized, or if this parameters could not be converted to
* the specified class.
- * @since Android 1.0
*/
public final <T extends AlgorithmParameterSpec> T getParameterSpec(Class<T> paramSpec)
throws InvalidParameterSpecException {
@@ -292,12 +272,11 @@
/**
* Returns this {@code AlgorithmParameters} in their default encoding
* format. The default encoding format is ASN.1.
- *
+ *
* @return the encoded parameters.
* @throws IOException
* if this {@code AlgorithmParameters} has already been
* initialized, or if this parameters could not be encoded.
- * @since Android 1.0
*/
public final byte[] getEncoded() throws IOException {
if (!initialized) {
@@ -309,14 +288,13 @@
/**
* Returns this {@code AlgorithmParameters} in the specified encoding
* format.
- *
+ *
* @param format
* the name of the encoding format.
* @return the encoded parameters.
* @throws IOException
* if this {@code AlgorithmParameters} has already been
* initialized, or if this parameters could not be encoded.
- * @since Android 1.0
*/
public final byte[] getEncoded(String format) throws IOException {
if (!initialized) {
@@ -328,10 +306,10 @@
/**
* Returns a string containing a concise, human-readable description of this
* {@code AlgorithmParameters}.
- *
+ *
* @return a printable representation for this {@code AlgorithmParameters}.
- * @since Android 1.0
*/
+ @Override
public final String toString() {
if (!initialized) {
return null;
diff --git a/libcore/security/src/main/java/java/security/AlgorithmParametersSpi.java b/libcore/security/src/main/java/java/security/AlgorithmParametersSpi.java
index 3bc8891..41b30bc 100644
--- a/libcore/security/src/main/java/java/security/AlgorithmParametersSpi.java
+++ b/libcore/security/src/main/java/java/security/AlgorithmParametersSpi.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
package java.security;
import java.io.IOException;
@@ -37,14 +32,13 @@
/**
* Initializes this {@code AlgorithmParametersSpi} with the specified
* {@code AlgorithmParameterSpec}.
- *
+ *
* @param paramSpec
* the parameter specification.
* @throws InvalidParameterSpecException
* if this {@code AlgorithmParametersSpi} has already been
* initialized or the given {@code paramSpec} is not appropriate
* for initializing this {@code AlgorithmParametersSpi}.
- * @since Android 1.0
*/
protected abstract void engineInit(AlgorithmParameterSpec paramSpec)
throws InvalidParameterSpecException;
@@ -53,20 +47,19 @@
* Initializes this {@code AlgorithmParametersSpi} with the specified
* {@code byte[]} using the default decoding format for parameters. The
* default encoding format is ASN.1.
- *
+ *
* @param params
* the encoded parameters.
* @throws IOException
* if this {@code AlgorithmParametersSpi} has already been
* initialized, or the parameter could not be encoded.
- * @since Android 1.0
*/
protected abstract void engineInit(byte[] params) throws IOException;
/**
* Initializes this {@code AlgorithmParametersSpi} with the specified
* {@code byte[]} using the specified decoding format.
- *
+ *
* @param params
* the encoded parameters.
* @param format
@@ -74,7 +67,6 @@
* @throws IOException
* if this {@code AlgorithmParametersSpi} has already been
* initialized, or the parameter could not be encoded.
- * @since Android 1.0
*/
protected abstract void engineInit(byte[] params, String format)
throws IOException;
@@ -82,7 +74,7 @@
/**
* Returns the {@code AlgorithmParameterSpec} for this {@code
* AlgorithmParametersSpi}.
- *
+ *
* @param paramSpec
* the type of the parameter specification in which this
* parameters should be converted.
@@ -92,7 +84,6 @@
* if this {@code AlgorithmParametersSpi} has already been
* initialized, or if this parameters could not be converted to
* the specified class.
- * @since Android 1.0
*/
protected abstract <T extends AlgorithmParameterSpec> T engineGetParameterSpec(
Class<T> paramSpec) throws InvalidParameterSpecException;
@@ -100,25 +91,23 @@
/**
* Returns the parameters in their default encoding format. The default
* encoding format is ASN.1.
- *
+ *
* @return the encoded parameters.
* @throws IOException
* if this {@code AlgorithmParametersSpi} has already been
* initialized, or if this parameters could not be encoded.
- * @since Android 1.0
*/
protected abstract byte[] engineGetEncoded() throws IOException;
/**
* Returns the parameters in the specified encoding format.
- *
+ *
* @param format
* the name of the encoding format.
* @return the encoded parameters.
* @throws IOException
* if this {@code AlgorithmParametersSpi} has already been
* initialized, or if this parameters could not be encoded.
- * @since Android 1.0
*/
protected abstract byte[] engineGetEncoded(String format)
throws IOException;
@@ -126,11 +115,10 @@
/**
* Returns a string containing a concise, human-readable description of this
* {@code AlgorithmParametersSpi}.
- *
+ *
* @return a printable representation for this {@code
* AlgorithmParametersSpi}.
- * @since Android 1.0
*/
protected abstract String engineToString();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/AllPermission.java b/libcore/security/src/main/java/java/security/AllPermission.java
index f4b8aad..c12bb27 100644
--- a/libcore/security/src/main/java/java/security/AllPermission.java
+++ b/libcore/security/src/main/java/java/security/AllPermission.java
@@ -22,11 +22,12 @@
* {@code AllPermission} represents the permission to perform any operation.
* Since its {@link #implies(Permission)} method always returns {@code true},
* granting this permission is equivalent to disabling security.
- *
- * @since Android 1.0
*/
public final class AllPermission extends Permission {
+ /**
+ * @serial
+ */
private static final long serialVersionUID = -2916474571451318075L;
// Permission name
@@ -40,12 +41,11 @@
* version is provided for class {@code Policy} so that it has a consistent
* call pattern across all permissions. The name and action list are both
* ignored.
- *
+ *
* @param name
* ignored.
* @param actions
* ignored.
- * @since Android 1.0
*/
public AllPermission(String name, String actions) {
super(ALL_PERMISSIONS);
@@ -53,8 +53,6 @@
/**
* Constructs a new instance of {@code AllPermission}.
- *
- * @since Android 1.0
*/
public AllPermission() {
super(ALL_PERMISSIONS);
@@ -65,15 +63,15 @@
* equality and returns {@code true} if the specified object is equal,
* {@code false} otherwise. To be equal, the given object needs to be an
* instance of {@code AllPermission}.
- *
+ *
* @param obj
* object to be compared for equality with this {@code
* AllPermission}.
* @return {@code true} if the specified object is equal to this {@code
* AllPermission}, otherwise {@code false}.
- * @since Android 1.0
* @see #hashCode
*/
+ @Override
public boolean equals(Object obj) {
return (obj instanceof AllPermission);
}
@@ -82,12 +80,12 @@
* Returns the hash code value for this {@code AllPermission}. Returns the
* same hash code for {@code AllPermission}s that are equal to each other as
* required by the general contract of {@link Object#hashCode}.
- *
+ *
* @return the hash code value for this {@code AllPermission}.
* @see Object#equals(Object)
* @see AllPermission#equals(Object)
- * @since Android 1.0
*/
+ @Override
public int hashCode() {
return 1;
}
@@ -96,10 +94,10 @@
* Returns the actions associated with this {@code AllPermission}. Since
* {@code AllPermission} objects allow all actions, this method returns
* always the string "<all actions>".
- *
+ *
* @return the actions associated with this {@code AllPermission}.
- * @since Android 1.0
*/
+ @Override
public String getActions() {
return ALL_ACTIONS;
}
@@ -107,12 +105,12 @@
/**
* Indicates whether the given permission is implied by this permission.
* {@code AllPermission} objects imply all other permissions.
- *
+ *
* @return always {@code true}.
* @param permission
* the permission to check.
- * @since Android 1.0
*/
+ @Override
public boolean implies(Permission permission) {
return true;
}
@@ -120,10 +118,10 @@
/**
* Returns a new {@code PermissionCollection} for holding permissions of
* this class.
- *
+ *
* @return a new {@code PermissionCollection}.
- * @since Android 1.0
*/
+ @Override
public PermissionCollection newPermissionCollection() {
return new AllPermissionCollection();
}
diff --git a/libcore/security/src/main/java/java/security/AllPermissionCollection.java b/libcore/security/src/main/java/java/security/AllPermissionCollection.java
index 000365d..5b28420 100644
--- a/libcore/security/src/main/java/java/security/AllPermissionCollection.java
+++ b/libcore/security/src/main/java/java/security/AllPermissionCollection.java
@@ -32,13 +32,9 @@
* single added instance.
*
* @see AllPermission
- * @since Android 1.0
*/
final class AllPermissionCollection extends PermissionCollection {
- /**
- * @com.intel.drl.spec_ref
- */
private static final long serialVersionUID = -4023755556366636806L;
private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField(
@@ -50,6 +46,7 @@
/**
* Adds an {@code AllPermission} to the collection.
*/
+ @Override
public void add(Permission permission) {
if (isReadOnly()) {
throw new SecurityException(Messages.getString("security.15")); //$NON-NLS-1$
@@ -64,6 +61,7 @@
/**
* Returns the enumeration of the collection.
*/
+ @Override
public Enumeration<Permission> elements() {
return new SingletonEnumeration<Permission>(all);
}
@@ -78,6 +76,7 @@
/**
* Constructor taking the single element.
+ * @param single the element
*/
public SingletonEnumeration(E single) {
element = single;
@@ -112,6 +111,7 @@
* @param permission
* the permission to check.
*/
+ @Override
public boolean implies(Permission permission) {
return all != null;
}
@@ -137,4 +137,4 @@
all = new AllPermission();
}
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/AuthProvider.java b/libcore/security/src/main/java/java/security/AuthProvider.java
index 5a3be77..15324b3 100644
--- a/libcore/security/src/main/java/java/security/AuthProvider.java
+++ b/libcore/security/src/main/java/java/security/AuthProvider.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
package java.security;
import javax.security.auth.Subject;
@@ -29,11 +24,12 @@
/**
* {@code AuthProvider} is an abstract superclass for Java Security {@code
* Provider} which provide login and logout.
- *
- * @since Android 1.0
*/
public abstract class AuthProvider extends Provider {
+ /**
+ * @serial
+ */
private static final long serialVersionUID = 4197859053084546461L;
/**
@@ -46,7 +42,6 @@
* the version of the provider.
* @param info
* a description of the provider.
- * @since Android 1.0
*/
protected AuthProvider(String name, double version, String info) {
super(name, version, info);
@@ -71,7 +66,6 @@
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this method.
- * @since Android 1.0
*/
public abstract void login(Subject subject, CallbackHandler handler) throws LoginException;
@@ -82,14 +76,12 @@
* the {@code SecurityPermission} {@code authProvider.NAME} (where NAME is
* the provider name) to be granted, otherwise a {@code SecurityException}
* will be thrown.
- * </p>
- *
+ *
* @throws LoginException
* if the logout fails.
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this method.
- * @since Android 1.0
*/
public abstract void logout() throws LoginException;
@@ -101,20 +93,18 @@
* If no handler is set, this {@code AuthProvider} uses the {@code
* CallbackHandler} specified by the {@code
* auth.login.defaultCallbackHandler} security property.
- * </p><p>
+ * <p>
* If a {@code SecurityManager} is installed, code calling this method needs
* the {@code SecurityPermission} {@code authProvider.NAME} (where NAME is
* the provider name) to be granted, otherwise a {@code SecurityException}
* will be thrown.
- * </p>
- *
+ *
* @param handler
* the handler to obtain authentication information from the
* caller.
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this method.
- * @since Android 1.0
*/
public abstract void setCallbackHandler(CallbackHandler handler);
}
diff --git a/libcore/security/src/main/java/java/security/BasicPermission.java b/libcore/security/src/main/java/java/security/BasicPermission.java
index 1d566ec..aa49cba 100644
--- a/libcore/security/src/main/java/java/security/BasicPermission.java
+++ b/libcore/security/src/main/java/java/security/BasicPermission.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Alexey V. Varlamov
-* @version $Revision$
-*/
-
package java.security;
import java.io.IOException;
@@ -38,14 +33,13 @@
* For example:
*
* <pre>
- * com.google.android.* grants all permissions under the com.google.android permission hierarchy
- * * grants all permissions
+ * java.io.* grants all permissions under the java.io permission hierarchy
+ * * grants all permissions
* </pre>
- * </p><p>
+ * <p>
* While this class ignores the action list in the
* {@link #BasicPermission(String, String)} constructor, subclasses may
* implement actions on top of this class.
- * </p>
*/
public abstract class BasicPermission extends Permission implements
Serializable {
@@ -55,12 +49,11 @@
/**
* Constructs a new instance of {@code BasicPermission} with the specified
* name.
- *
+ *
* @param name
* the name of the permission.
* @throws NullPointerException if {@code name} is {@code null}.
* @throws IllegalArgumentException if {@code name.length() == 0}.
- * @since Android 1.0
*/
public BasicPermission(String name) {
super(name);
@@ -70,7 +63,7 @@
/**
* Constructs a new instance of {@code BasicPermission} with the specified
* name. The {@code action} parameter is ignored.
- *
+ *
* @param name
* the name of the permission.
* @param action
@@ -79,7 +72,6 @@
* if {@code name} is {@code null}.
* @throws IllegalArgumentException
* if {@code name.length() == 0}.
- * @since Android 1.0
*/
public BasicPermission(String name, String action) {
super(name);
@@ -105,15 +97,14 @@
* <p>
* The {@link #implies(Permission)} method should be used for making access
* control checks.
- * </p>
- *
+ *
* @param obj
* object to be compared for equality with this {@code
* BasicPermission}.
* @return {@code true} if the specified object is equal to this {@code
* BasicPermission}, otherwise {@code false}.
- * @since Android 1.0
*/
+ @Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
@@ -129,12 +120,12 @@
* Returns the hash code value for this {@code BasicPermission}. Returns the
* same hash code for {@code BasicPermission}s that are equal to each other
* as required by the general contract of {@link Object#hashCode}.
- *
+ *
* @return the hash code value for this {@code BasicPermission}.
* @see Object#equals(Object)
* @see BasicPermission#equals(Object)
- * @since Android 1.0
*/
+ @Override
public int hashCode() {
return getName().hashCode();
}
@@ -142,23 +133,23 @@
/**
* Returns the actions associated with this permission. Since {@code
* BasicPermission} instances have no actions, an empty string is returned.
- *
+ *
* @return an empty string.
- * @since Android 1.0
*/
+ @Override
public String getActions() {
return ""; //$NON-NLS-1$
}
/**
* Indicates whether the specified permission is implied by this permission.
- *
+ *
* @param permission
* the permission to check against this permission.
* @return {@code true} if the specified permission is implied by this
* permission, {@code false} otherwise.
- * @since Android 1.0
*/
+ @Override
public boolean implies(Permission permission) {
if (permission != null && permission.getClass() == this.getClass()) {
return nameImplies(getName(), permission.getName());
@@ -204,12 +195,11 @@
* stored in it when checking if the collection implies a permission.
* Instead, it assumes that if the type of the permission is correct, and
* the name of the permission is correct, there is a match.
- * </p>
- *
+ *
* @return an empty {@link PermissionCollection} for holding permissions.
* @see BasicPermissionCollection
- * @since Android 1.0
*/
+ @Override
public PermissionCollection newPermissionCollection() {
return new BasicPermissionCollection();
}
@@ -222,4 +212,4 @@
in.defaultReadObject();
checkName(this.getName());
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/BasicPermissionCollection.java b/libcore/security/src/main/java/java/security/BasicPermissionCollection.java
index eb80503..820ae7f 100644
--- a/libcore/security/src/main/java/java/security/BasicPermissionCollection.java
+++ b/libcore/security/src/main/java/java/security/BasicPermissionCollection.java
@@ -37,7 +37,6 @@
*
* @see BasicPermission
* @see PermissionCollection
- * @since Android 1.0
*/
final class BasicPermissionCollection extends PermissionCollection {
@@ -63,6 +62,7 @@
*
* @see java.security.PermissionCollection#add(java.security.Permission)
*/
+ @Override
public void add(Permission permission) {
if (isReadOnly()) {
throw new SecurityException(Messages.getString("security.15")); //$NON-NLS-1$
@@ -82,8 +82,6 @@
permission));
} else {
// this is the first element provided that another thread did not add
- // BEGIN android-changed
- // copied from a newer version of harmony
synchronized (this) {
if (permClass != null && inClass != permClass) {
throw new IllegalArgumentException(Messages.getString("security.16", //$NON-NLS-1$
@@ -91,7 +89,6 @@
}
permClass = inClass;
}
- // END android-changed
}
String name = permission.getName();
@@ -102,6 +99,7 @@
/**
* Returns enumeration of contained elements.
*/
+ @Override
public Enumeration<Permission> elements() {
return Collections.enumeration(items.values());
}
@@ -115,6 +113,7 @@
* the permission to check.
* @see Permission
*/
+ @Override
public boolean implies(Permission permission) {
if (permission == null || permission.getClass() != permClass) {
return false;
@@ -162,16 +161,10 @@
* <dd>The class to which all {@code BasicPermission}s in this
* BasicPermissionCollection belongs.
* <dt>Hashtable<K,V> permissions
- * <dd>The
- *
- * <pre>
- * BasicPermission
- * </pre>
- *
- * s in this {@code BasicPermissionCollection}. All {@code BasicPermission}s
- * in the collection must belong to the same class. The Hashtable is indexed
- * by the {@code BasicPermission} name; the value of the Hashtable entry is
- * the permission.
+ * <dd>The {@code BasicPermission}s in this collection. All {@code
+ * BasicPermission}s in the collection must belong to the same class. The
+ * Hashtable is indexed by the {@code BasicPermission} name; the value of
+ * the Hashtable entry is the permission.
* </dl>
*/
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
@@ -191,8 +184,6 @@
ObjectInputStream.GetField fields = in.readFields();
items = new HashMap<String, Permission>();
- // BEGIN android-changed
- // copied from a newer version of harmony
synchronized (this) {
permClass = (Class<? extends Permission>)fields.get("permClass", null); //$NON-NLS-1$
items.putAll((Hashtable<String, Permission>) fields.get(
@@ -207,6 +198,5 @@
throw new InvalidObjectException(Messages.getString("security.25")); //$NON-NLS-1$
}
}
- // END android-changed
}
}
diff --git a/libcore/security/src/main/java/java/security/Certificate.java b/libcore/security/src/main/java/java/security/Certificate.java
index bf9a1ae..b30352d 100644
--- a/libcore/security/src/main/java/java/security/Certificate.java
+++ b/libcore/security/src/main/java/java/security/Certificate.java
@@ -15,15 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
-// BEGIN android-note
-// Added Deprecated annotation.
-// END android-note
-
package java.security;
import java.io.IOException;
@@ -36,9 +27,8 @@
* validity of itself. It's in the responsibility of the application to verify
* the validity of its certificates.
*
- * @deprecated Replaced by behavior in {@link javax.security.cert}
+ * @deprecated Replaced by behavior in {@link java.security.cert}
* @see java.security.cert.Certificate
- * @since Android 1.0
*/
@Deprecated
public interface Certificate {
@@ -47,7 +37,7 @@
* Decodes a certificate from the given {@code InputStream}. The format of
* the data to encode must be that identified by {@link #getFormat()} and
* encoded by {@link #encode(OutputStream)}.
- *
+ *
* @param stream
* the {@code InputStream} to read from.
* @throws KeyException
@@ -56,7 +46,6 @@
* if an exception is thrown by accessing the provided stream.
* @see #encode(OutputStream)
* @see #getFormat()
- * @since Android 1.0
*/
public void decode(InputStream stream) throws KeyException, IOException;
@@ -64,7 +53,7 @@
* Encodes this certificate to an output stream. The
* {@link #decode(InputStream)} method must be able to decode the format
* written by this method.
- *
+ *
* @param stream
* the {@code OutputStream} to encode this certificate to.
* @throws KeyException
@@ -72,15 +61,13 @@
* @throws IOException
* if an exception is thrown by accessing the provided stream.
* @see #decode(InputStream)
- * @since Android 1.0
*/
public void encode(OutputStream stream) throws KeyException, IOException;
/**
* Returns a string identifying the format of this certificate.
- *
+ *
* @return a string identifying the format of this certificate.
- * @since Android 1.0
*/
public String getFormat();
@@ -88,42 +75,38 @@
* Returns the guarantor of this certificate. That guarantor guarantees,
* that the public key of this certificate is from the principal returned by
* {@link #getPrincipal()}.
- *
+ *
* @return the guarantor of this certificate.
* @see #getPrincipal()
- * @since Android 1.0
*/
public Principal getGuarantor();
/**
* Returns the principal of this certificate. The principal is guaranteed by
* the guarantor returned by {@link #getGuarantor()}.
- *
+ *
* @return the principal of this certificate.
* @see #getGuarantor()
- * @since Android 1.0
*/
public Principal getPrincipal();
/**
* Returns the public key of this certificate. The public key is guaranteed
* by the guarantor to belong to the principal.
- *
+ *
* @return the public key of this certificate.
* @see #getGuarantor()
* @see Certificate#getPrincipal()
- * @since Android 1.0
*/
public PublicKey getPublicKey();
/**
* Returns a string containing a concise, human-readable description of the
* this {@code Certificate}.
- *
+ *
* @param detailed
* whether or not this method should return detailed information.
* @return a string representation of this certificate.
- * @since Android 1.0
*/
public String toString(boolean detailed);
}
diff --git a/libcore/security/src/main/java/java/security/CodeSigner.java b/libcore/security/src/main/java/java/security/CodeSigner.java
index 0719e8f..24d2b55 100644
--- a/libcore/security/src/main/java/java/security/CodeSigner.java
+++ b/libcore/security/src/main/java/java/security/CodeSigner.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision$
-*/
-
package java.security;
import java.io.Serializable;
@@ -29,8 +24,6 @@
/**
* {@code CodeSigner} represents a signer of code. Instances are immutable.
- *
- * @since Android 1.0
*/
public final class CodeSigner implements Serializable {
@@ -45,7 +38,7 @@
/**
* Constructs a new instance of {@code CodeSigner}.
- *
+ *
* @param signerCertPath
* the certificate path associated with this code signer.
* @param timestamp
@@ -53,7 +46,6 @@
* null}.
* @throws NullPointerException
* if {@code signerCertPath} is {@code null}.
- * @since Android 1.0
*/
public CodeSigner(CertPath signerCertPath, Timestamp timestamp) {
if (signerCertPath == null) {
@@ -68,14 +60,14 @@
* Returns {@code true} if the specified object is also an instance of
* {@code CodeSigner}, the two {@code CodeSigner} encapsulate the same
* certificate path and the same time stamp, if present in both.
- *
+ *
* @param obj
* object to be compared for equality with this {@code
* CodeSigner}.
* @return {@code true} if the specified object is equal to this {@code
* CodeSigner}, otherwise {@code false}.
- * @since Android 1.0
*/
+ @Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
@@ -93,9 +85,8 @@
/**
* Returns the certificate path associated with this {@code CodeSigner}.
- *
+ *
* @return the certificate path associated with this {@code CodeSigner}.
- * @since Android 1.0
*/
public CertPath getSignerCertPath() {
return signerCertPath;
@@ -103,10 +94,9 @@
/**
* Returns the time stamp associated with this {@code CodeSigner}.
- *
+ *
* @return the time stamp associated with this {@code CodeSigner}, maybe
* {@code null}.
- * @since Android 1.0
*/
public Timestamp getTimestamp() {
return timestamp;
@@ -116,12 +106,12 @@
* Returns the hash code value for this {@code CodeSigner}. Returns the same
* hash code for {@code CodeSigner}s that are equal to each other as
* required by the general contract of {@link Object#hashCode}.
- *
+ *
* @return the hash code value for this {@code CodeSigner}.
* @see Object#equals(Object)
* @see CodeSigner#equals(Object)
- * @since Android 1.0
*/
+ @Override
public int hashCode() {
if (hash == 0) {
hash = signerCertPath.hashCode()
@@ -134,14 +124,13 @@
* Returns a string containing a concise, human-readable description of the
* this {@code CodeSigner} including its first certificate and its time
* stamp, if present.
- *
+ *
* @return a printable representation for this {@code CodeSigner}.
- * @since Android 1.0
*/
+ @Override
public String toString() {
// There is no any special reason for '256' here, it's taken abruptly
- // FIXME: 1.5 StringBuffer => StringBuilder
- StringBuffer buf = new StringBuffer(256);
+ StringBuilder buf = new StringBuilder(256);
// The javadoc says nothing, and the others implementations behavior seems as
// dumping only the first certificate. Well, let's do the same.
buf.append("CodeSigner [").append(signerCertPath.getCertificates().get(0)); //$NON-NLS-1$
@@ -151,4 +140,4 @@
buf.append("]"); //$NON-NLS-1$
return buf.toString();
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/CodeSource.java b/libcore/security/src/main/java/java/security/CodeSource.java
index f4da89c..96a4b8c5 100644
--- a/libcore/security/src/main/java/java/security/CodeSource.java
+++ b/libcore/security/src/main/java/java/security/CodeSource.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision$
-*/
-
package java.security;
import java.io.ByteArrayInputStream;
@@ -48,10 +43,9 @@
* {@code CodeSource} encapsulates the location from where code is loaded and
* the certificates that were used to verify that code. This information is used
* by {@code SecureClassLoader} to define protection domains for loaded classes.
- *
+ *
* @see SecureClassLoader
* @see ProtectionDomain
- * @since Android 1.0
*/
public class CodeSource implements Serializable {
@@ -76,14 +70,13 @@
/**
* Constructs a new instance of {@code CodeSource} with the specified
* {@code URL} and the {@code Certificate}s.
- *
+ *
* @param location
* the {@code URL} representing the location from where code is
* loaded, maybe {@code null}.
* @param certs
* the {@code Certificate} used to verify the code, loaded from
* the specified {@code location}, maybe {@code null}.
- * @since Android 1.0
*/
public CodeSource(URL location, Certificate[] certs) {
this.location = location;
@@ -96,14 +89,13 @@
/**
* Constructs a new instance of {@code CodeSource} with the specified
* {@code URL} and the {@code CodeSigner}s.
- *
+ *
* @param location
* the {@code URL} representing the location from where code is
* loaded, maybe {@code null}.
* @param signers
* the {@code CodeSigner}s of the code, loaded from the specified
* {@code location}. Maybe {@code null}.
- * @since Android 1.0
*/
public CodeSource(URL location, CodeSigner[] signers) {
this.location = location;
@@ -119,14 +111,14 @@
* {@code CodeSource}, points to the same {@code URL} location and the two
* code sources encapsulate the same {@code Certificate}s. The order of the
* {@code Certificate}s is ignored by this method.
- *
+ *
* @param obj
* object to be compared for equality with this {@code
* CodeSource}.
* @return {@code true} if the specified object is equal to this {@code
* CodeSource}, otherwise {@code false}.
- * @since Android 1.0
*/
+ @Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
@@ -169,11 +161,9 @@
* <p>
* External modifications of the returned {@code Certificate[]} has no
* impact on this {@code CodeSource}.
- * </p>
- *
+ *
* @return the certificates of this {@code CodeSource} or {@code null} if
* there is none.
- * @since Android 1.0
*/
public final Certificate[] getCertificates() {
getCertificatesNoClone();
@@ -213,10 +203,9 @@
* {@link #CodeSource(URL, Certificate[])} constructor was used to create
* this instance, the signers are obtained from the supplied certificates.
* Only X.509 certificates are analyzed.
- *
+ *
* @return the signers of this {@code CodeSource}, or {@code null} if there
* is none.
- * @since Android 1.0
*/
public final CodeSigner[] getCodeSigners() {
if (signers != null) {
@@ -308,9 +297,8 @@
/**
* Returns the location of this {@code CodeSource}.
- *
+ *
* @return the location of this {@code CodeSource}, maybe {@code null}.
- * @since Android 1.0
*/
public final URL getLocation() {
return location;
@@ -321,12 +309,12 @@
* Returns the same hash code for {@code CodeSource}s that are
* equal to each other as required by the general contract of
* {@link Object#hashCode}.
- *
+ *
* @return the hash code value for this {@code CodeSource}.
* @see Object#equals(Object)
* @see CodeSource#equals(Object)
- * @since Android 1.0
*/
+ @Override
public int hashCode() {
//
// hashCode() is undocumented there. Should we also use certs[i] to
@@ -385,21 +373,20 @@
* location file with the '/' appended to it.
* </ul>
* Examples for locations that imply the location
- * "http://code.google.com/android/security.apk":
- *
+ * "http://harmony.apache.org/milestones/M9/apache-harmony.jar":
+ *
* <pre>
* http:
- * http://*/android/*
- * http://*.google.com/android/*
- * http://code.google.com/android/-
- * http://code.google.com/android/security.apk
+ * http://*/milestones/M9/*
+ * http://*.apache.org/milestones/M9/*
+ * http://harmony.apache.org/milestones/-
+ * http://harmony.apache.org/milestones/M9/apache-harmony.jar
* </pre>
- *
+ *
* @param cs
* the code source to check.
* @return {@code true} if the argument code source is implied by this
* {@code CodeSource}, otherwise {@code false}.
- * @since Android 1.0
*/
public boolean implies(CodeSource cs) {
//
@@ -551,10 +538,10 @@
* Returns a string containing a concise, human-readable description of the
* this {@code CodeSource} including its location, its certificates and its
* signers.
- *
+ *
* @return a printable representation for this {@code CodeSource}.
- * @since Android 1.0
*/
+ @Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append("CodeSource, url="); //$NON-NLS-1$
diff --git a/libcore/security/src/main/java/java/security/DigestException.java b/libcore/security/src/main/java/java/security/DigestException.java
index d579885..0d0a1ee 100644
--- a/libcore/security/src/main/java/java/security/DigestException.java
+++ b/libcore/security/src/main/java/java/security/DigestException.java
@@ -15,17 +15,10 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
package java.security;
/**
*{@code DigestException} is a general message digest exception.
- *
- *@since Android 1.0
*/
public class DigestException extends GeneralSecurityException {
@@ -34,10 +27,9 @@
/**
* Constructs a new instance of {@code DigestException} with the
* given message.
- *
+ *
* @param msg
* the detail message for this exception.
- * @since Android 1.0
*/
public DigestException(String msg) {
super(msg);
@@ -45,8 +37,6 @@
/**
* Constructs a new instance of {@code DigestException}.
- *
- * @since Android 1.0
*/
public DigestException() {
}
@@ -54,12 +44,11 @@
/**
* Constructs a new instance of {@code DigestException} with the
* given message and the cause.
- *
+ *
* @param message
* the detail message for this exception.
* @param cause
* the exception which is the cause for this exception.
- * @since Android 1.0
*/
public DigestException(String message, Throwable cause) {
super(message, cause);
@@ -68,10 +57,9 @@
/**
* Constructs a new instance of {@code DigestException} with the
* cause.
- *
+ *
* @param cause
* the exception which is the cause for this exception.
- * @since Android 1.0
*/
public DigestException(Throwable cause) {
super(cause);
diff --git a/libcore/security/src/main/java/java/security/DigestInputStream.java b/libcore/security/src/main/java/java/security/DigestInputStream.java
index 0db7613..26433fa 100644
--- a/libcore/security/src/main/java/java/security/DigestInputStream.java
+++ b/libcore/security/src/main/java/java/security/DigestInputStream.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Vladimir N. Molotkov
-* @version $Revision$
-*/
-
package java.security;
import java.io.FilterInputStream;
@@ -29,15 +24,11 @@
/**
* {@code DigestInputStream} is a {@code FilterInputStream} which maintains an
* associated message digest.
- *
- * @since Android 1.0
*/
public class DigestInputStream extends FilterInputStream {
/**
* The message digest for this stream.
- *
- * @since Android 1.0
*/
protected MessageDigest digest;
@@ -47,12 +38,11 @@
/**
* Constructs a new instance of this {@code DigestInputStream}, using the
* given {@code stream} and the {@code digest}.
- *
+ *
* @param stream
* the input stream.
* @param digest
* the message digest.
- * @since Android 1.0
*/
public DigestInputStream(InputStream stream, MessageDigest digest) {
super(stream);
@@ -61,9 +51,8 @@
/**
* Returns the message digest for this stream.
- *
+ *
* @return the message digest for this stream.
- * @since Android 1.0
*/
public MessageDigest getMessageDigest() {
return digest;
@@ -71,10 +60,9 @@
/**
* Sets the message digest which this stream will use.
- *
+ *
* @param digest
* the message digest which this stream will use.
- * @since Android 1.0
*/
public void setMessageDigest(MessageDigest digest) {
this.digest = digest;
@@ -85,13 +73,12 @@
* for the byte if this function is {@link #on(boolean)}.
* <p>
* This operation is blocking.
- * </p>
- *
+ *
* @return the byte which was read or -1 at end of stream.
* @throws IOException
* if reading the source stream causes an {@code IOException}.
- * @since Android 1.0
*/
+ @Override
public int read() throws IOException {
// read the next byte
int byteRead = in.read();
@@ -111,8 +98,7 @@
* {@link #on(boolean)}.
* <p>
* This operation is blocking.
- * </p>
- *
+ *
* @param b
* the byte array in which to store the bytes
* @param off
@@ -124,8 +110,8 @@
* filtered stream has been reached while reading
* @throws IOException
* if reading the source stream causes an {@code IOException}
- * @since Android 1.0
*/
+ @Override
public int read(byte[] b, int off, int len) throws IOException {
// read next up to len bytes
int bytesRead = in.read(b, off, len);
@@ -141,11 +127,11 @@
/**
* Enables or disables the digest function (default is on).
- *
+ *
* @param on
* {@code true} if the digest should be computed, {@code false}
* otherwise.
- * @since Android 1.0
+ * @see MessageDigest
*/
public void on(boolean on) {
isOn = on;
@@ -154,10 +140,10 @@
/**
* Returns a string containing a concise, human-readable description of this
* {@code DigestInputStream} including the digest.
- *
+ *
* @return a printable representation for this {@code DigestInputStream}.
- * @since Android 1.0
*/
+ @Override
public String toString() {
return super.toString() + ", " + digest.toString() + //$NON-NLS-1$
(isOn ? ", is on" : ", is off"); //$NON-NLS-1$ //$NON-NLS-2$
diff --git a/libcore/security/src/main/java/java/security/DigestOutputStream.java b/libcore/security/src/main/java/java/security/DigestOutputStream.java
index 858f8dd..f4cd659 100644
--- a/libcore/security/src/main/java/java/security/DigestOutputStream.java
+++ b/libcore/security/src/main/java/java/security/DigestOutputStream.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Vladimir N. Molotkov
-* @version $Revision$
-*/
-
package java.security;
import java.io.FilterOutputStream;
@@ -34,8 +29,6 @@
/**
* The message digest for this stream.
- *
- * @since Android 1.0
*/
protected MessageDigest digest;
@@ -45,12 +38,11 @@
/**
* Constructs a new instance of this {@code DigestOutputStream}, using the
* given {@code stream} and the {@code digest}.
- *
+ *
* @param stream
* the output stream.
* @param digest
* the message digest.
- * @since Android 1.0
*/
public DigestOutputStream(OutputStream stream, MessageDigest digest) {
super(stream);
@@ -59,9 +51,8 @@
/**
* Returns the message digest for this stream.
- *
+ *
* @return the message digest for this stream.
- * @since Android 1.0
*/
public MessageDigest getMessageDigest() {
return digest;
@@ -69,10 +60,9 @@
/**
* Sets the message digest which this stream will use.
- *
+ *
* @param digest
* the message digest which this stream will use.
- * @since Android 1.0
*/
public void setMessageDigest(MessageDigest digest) {
this.digest = digest;
@@ -81,13 +71,13 @@
/**
* Writes the specified {@code int} to the stream. Updates the digest if
* this function is {@link #on(boolean)}.
- *
+ *
* @param b
* the byte to be written.
* @throws IOException
* if writing to the stream causes a {@code IOException}
- * @since Android 1.0
*/
+ @Override
public void write(int b) throws IOException {
// update digest only if digest functionality is on
if (isOn) {
@@ -100,7 +90,7 @@
/**
* Writes {@code len} bytes into the stream, starting from the specified
* offset. Updates the digest if this function is {@link #on(boolean)}.
- *
+ *
* @param b
* the buffer to write to.
* @param off
@@ -109,8 +99,8 @@
* the number of bytes in {@code b} to write.
* @throws IOException
* if writing to the stream causes an {@code IOException}.
- * @since Android 1.0
*/
+ @Override
public void write(byte[] b, int off, int len) throws IOException {
// update digest only if digest functionality is on
if (isOn) {
@@ -122,11 +112,11 @@
/**
* Enables or disables the digest function (default is on).
- *
+ *
* @param on
* {@code true} if the digest should be computed, {@code false}
* otherwise.
- * @since Android 1.0
+ * @see MessageDigest
*/
public void on(boolean on) {
isOn = on;
@@ -135,10 +125,10 @@
/**
* Returns a string containing a concise, human-readable description of this
* {@code DigestOutputStream} including the digest.
- *
+ *
* @return a printable representation for this {@code DigestOutputStream}.
- * @since Android 1.0
*/
+ @Override
public String toString() {
return super.toString() + ", " + digest.toString() + //$NON-NLS-1$
(isOn ? ", is on" : ", is off"); //$NON-NLS-1$ //$NON-NLS-2$
diff --git a/libcore/security/src/main/java/java/security/DomainCombiner.java b/libcore/security/src/main/java/java/security/DomainCombiner.java
index 501c419..36433b3 100644
--- a/libcore/security/src/main/java/java/security/DomainCombiner.java
+++ b/libcore/security/src/main/java/java/security/DomainCombiner.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision$
-*/
-
package java.security;
/**
@@ -29,7 +24,6 @@
* @see AccessControlContext
* @see AccessControlContext#AccessControlContext(AccessControlContext,
* DomainCombiner)
- * @since Android 1.0
*/
public interface DomainCombiner {
@@ -37,7 +31,7 @@
* Returns a combination of the two provided {@code ProtectionDomain}
* arrays. Implementers can simply merge the two arrays into one, remove
* duplicates and perform other optimizations.
- *
+ *
* @param current
* the protection domains of the current execution thread (since
* the most recent call to {@link AccessController#doPrivileged}
@@ -47,7 +41,6 @@
* null}.
* @return a single {@code ProtectionDomain} array computed from the two
* provided arrays.
- * @since Android 1.0
*/
ProtectionDomain[] combine(ProtectionDomain[] current,
ProtectionDomain[] assigned);
diff --git a/libcore/security/src/main/java/java/security/GeneralSecurityException.java b/libcore/security/src/main/java/java/security/GeneralSecurityException.java
index 2a1cacb..78fca29 100644
--- a/libcore/security/src/main/java/java/security/GeneralSecurityException.java
+++ b/libcore/security/src/main/java/java/security/GeneralSecurityException.java
@@ -15,18 +15,11 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
package java.security;
/**
* {@code GeneralSecurityException} is a general security exception and the
* superclass for all security specific exceptions.
- *
- * @since Android 1.0
*/
public class GeneralSecurityException extends Exception {
@@ -35,10 +28,9 @@
/**
* Constructs a new instance of {@code GeneralSecurityException} with the
* given message.
- *
+ *
* @param msg
* the detail message for this exception.
- * @since Android 1.0
*/
public GeneralSecurityException(String msg) {
super(msg);
@@ -46,8 +38,6 @@
/**
* Constructs a new instance of {@code GeneralSecurityException}.
- *
- * @since Android 1.0
*/
public GeneralSecurityException() {
}
@@ -55,12 +45,11 @@
/**
* Constructs a new instance of {@code GeneralSecurityException} with the
* given message and the cause.
- *
+ *
* @param message
* the detail message for this exception.
* @param cause
* the exception which is the cause for this exception.
- * @since Android 1.0
*/
public GeneralSecurityException(String message, Throwable cause) {
super(message, cause);
@@ -69,10 +58,9 @@
/**
* Constructs a new instance of {@code GeneralSecurityException} with the
* cause.
- *
+ *
* @param cause
* the exception which is the cause for this exception.
- * @since Android 1.0
*/
public GeneralSecurityException(Throwable cause) {
super(cause);
diff --git a/libcore/security/src/main/java/java/security/Guard.java b/libcore/security/src/main/java/java/security/Guard.java
index 1e4d270..b652054 100644
--- a/libcore/security/src/main/java/java/security/Guard.java
+++ b/libcore/security/src/main/java/java/security/Guard.java
@@ -15,17 +15,10 @@
* limitations under the License.
*/
-/**
-* @author Alexey V. Varlamov
-* @version $Revision$
-*/
-
package java.security;
/**
* {@code Guard} implementors protect access to other objects.
- *
- * @since Android 1.0
*/
public interface Guard {
@@ -33,12 +26,11 @@
* Checks whether access to the specified {@code Object} should be granted.
* This method returns silently if access is granted, otherwise a {@code
* SecurityException} is thrown.
- *
+ *
* @param object
* the object to be protected by this {@code Guard}.
* @throws SecurityException
* if access is not granted.
- * @since Android 1.0
*/
public void checkGuard(Object object) throws SecurityException;
}
diff --git a/libcore/security/src/main/java/java/security/GuardedObject.java b/libcore/security/src/main/java/java/security/GuardedObject.java
index a64d634..34a5113 100644
--- a/libcore/security/src/main/java/java/security/GuardedObject.java
+++ b/libcore/security/src/main/java/java/security/GuardedObject.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Alexey V. Varlamov
-* @version $Revision$
-*/
-
package java.security;
import java.io.IOException;
@@ -28,8 +23,6 @@
/**
* {@code GuardedObject} controls access to an object, by checking all requests
* for the object with a {@code Guard}.
- *
- * @since Android 1.0
*/
public class GuardedObject implements Serializable {
@@ -42,13 +35,12 @@
/**
* Constructs a new instance of {@code GuardedObject} which protects access
* to the specified {@code Object} using the specified {@code Guard}.
- *
+ *
* @param object
* the {@code Object} to protect.
* @param guard
* the {@code Guard} which protects the specified {@code Object},
* maybe {@code null}.
- * @since Android 1.0
*/
public GuardedObject(Object object, Guard guard) {
this.object = object;
@@ -59,11 +51,10 @@
* Returns the guarded {@code Object} if the associated {@code Guard}
* permits access. If access is not granted, then a {@code
* SecurityException} is thrown.
- *
+ *
* @return the guarded object.
* @exception SecurityException
* if access is not granted to the guarded object.
- * @since Android 1.0
*/
public Object getObject() throws SecurityException {
if (guard != null) {
diff --git a/libcore/security/src/main/java/java/security/Identity.java b/libcore/security/src/main/java/java/security/Identity.java
index 7111029..d55cd3a 100644
--- a/libcore/security/src/main/java/java/security/Identity.java
+++ b/libcore/security/src/main/java/java/security/Identity.java
@@ -15,15 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision$
-*/
-
-// BEGIN android-note
-// Added Deprecated annotation.
-// END android-note
-
package java.security;
import java.io.Serializable;
@@ -34,11 +25,10 @@
/**
* {@code Identity} represents an identity like a person or a company.
- *
+ *
* @deprecated The functionality of this class has been replace by
* {@link Principal}, {@link KeyStore} and the {@code
* java.security.cert} package.
- * @since Android 1.0
*/
@Deprecated
public abstract class Identity implements Principal, Serializable {
@@ -56,18 +46,15 @@
/**
* Constructs a new instance of {@code Identity}.
- *
- * @since Android 1.0
*/
protected Identity() {
}
/**
* Creates a new instance of {@code Identity} with the specified name.
- *
+ *
* @param name
* the name of this {@code Identity}.
- * @since Android 1.0
*/
public Identity(String name) {
this.name = name;
@@ -76,7 +63,7 @@
/**
* Creates a new instance of {@code Identity} with the specified name and
* the scope of this {@code Identity}.
- *
+ *
* @param name
* the name of this {@code Identity}.
* @param scope
@@ -84,7 +71,6 @@
* @throws KeyManagementException
* if an {@code Identity} with the same name is already present
* in the specified scope.
- * @since Android 1.0
*/
public Identity(String name, IdentityScope scope)
throws KeyManagementException {
@@ -101,8 +87,7 @@
* If a {@code SecurityManager} is installed, code calling this method needs
* the {@code SecurityPermission} {@code addIdentityCertificate} to be
* granted, otherwise a {@code SecurityException} will be thrown.
- * </p>
- *
+ *
* @param certificate
* the {@code Certificate} to be added to this {@code Identity}.
* @throws KeyManagementException
@@ -110,7 +95,6 @@
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this method.
- * @since Android 1.0
*/
public void addCertificate(Certificate certificate)
throws KeyManagementException {
@@ -163,7 +147,7 @@
* the {@code SecurityPermission} {@code "removeIdentityCertificate"} to be
* granted, otherwise a {@code SecurityException} will be thrown.
* <p>
- *
+ *
* @param certificate
* the {@code Certificate} to be removed.
* @throws KeyManagementException
@@ -171,7 +155,6 @@
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this method.
- * @since Android 1.0
*/
public void removeCertificate(Certificate certificate)
throws KeyManagementException {
@@ -196,9 +179,8 @@
* Returns the certificates for this {@code Identity}. External
* modifications of the returned array has no impact on this {@code
* Identity}.
- *
+ *
* @return the {@code Certificates} for this {@code Identity}
- * @since Android 1.0
*/
public Certificate[] certificates() {
if (certificates == null) {
@@ -219,13 +201,11 @@
* <p>
* To be equal, two {@code Identity} objects need to have the same name and
* the same public keys.
- * </p>
- *
+ *
* @param identity
* the identity to check for equality.
* @return {@code true} if the {@code Identity} objects are equal, {@code
* false} otherwise.
- * @since Android 1.0
*/
protected boolean identityEquals(Identity identity) {
if (!name.equals(identity.name)) {
@@ -245,12 +225,11 @@
/**
* Returns a string containing a concise, human-readable description of the
* this {@code Identity}.
- *
+ *
* @param detailed
* whether or not this method should return detailed information.
* @return a printable representation for this {@code Permission}.
- * @since Android 1.0
- */
+ */
public String toString(boolean detailed) {
String s = toString();
if (detailed) {
@@ -264,9 +243,8 @@
/**
* Returns the {@code IdentityScope} of this {@code Identity}.
- *
+ *
* @return the {@code IdentityScope} of this {@code Identity}.
- * @since Android 1.0
*/
public final IdentityScope getScope() {
return scope;
@@ -281,8 +259,7 @@
* If a {@code SecurityManager} is installed, code calling this method needs
* the {@code SecurityPermission} {@code setIdentityPublicKey} to be
* granted, otherwise a {@code SecurityException} will be thrown.
- * </p>
- *
+ *
* @param key
* the {@code PublicKey} to be set.
* @throws KeyManagementException
@@ -291,7 +268,6 @@
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this method.
- * @since Android 1.0
*/
public void setPublicKey(PublicKey key) throws KeyManagementException {
SecurityManager sm = System.getSecurityManager();
@@ -315,9 +291,8 @@
/**
* Returns the {@code PublicKey} associated with this {@code Identity}.
- *
+ *
* @return the {@code PublicKey} associated with this {@code Identity}.
- * @since Android 1.0
*/
public PublicKey getPublicKey() {
return publicKey;
@@ -332,13 +307,12 @@
* If a {@code SecurityManager} is installed, code calling this method needs
* the {@code SecurityPermission} {@code setIdentityInfo} to be granted,
* otherwise a {@code SecurityException} will be thrown.
- *
+ *
* @param info
* the information to be set.
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this method.
- * @since Android 1.0
*/
public void setInfo(String info) {
SecurityManager sm = System.getSecurityManager();
@@ -353,9 +327,8 @@
/**
* Returns the information string of this {@code Identity}.
- *
+ *
* @return the information string of this {@code Identity}.
- * @since Android 1.0
*/
public String getInfo() {
return info;
@@ -369,14 +342,14 @@
* returns {@code true} if the specified object is equal, {@code false}
* otherwise. {@code Identity} objects are considered equal, if they have
* the same name and are in the same scope.
- *
+ *
* @param obj
* object to be compared for equality with this {@code
* Identity}.
* @return {@code true} if the specified object is equal to this {@code
* Identity}, otherwise {@code false}.
- * @since Android 1.0
*/
+ @Override
public final boolean equals(Object obj) {
if (this == obj) {
return true;
@@ -397,9 +370,8 @@
/**
* Returns the name of this {@code Identity}.
- *
+ *
* @return the name of this {@code Identity}.
- * @since Android 1.0
*/
public final String getName() {
return name;
@@ -412,12 +384,12 @@
* Returns the hash code value for this {@code Identity}. Returns the same
* hash code for {@code Identity}s that are equal to each other as required
* by the general contract of {@link Object#hashCode}.
- *
+ *
* @return the hash code value for this {@code Identity}.
* @see Object#equals(Object)
* @see Identity#equals(Object)
- * @since Android 1.0
*/
+ @Override
public int hashCode() {
int hash = 0;
if (name != null) {
@@ -439,22 +411,22 @@
* If a {@code SecurityManager} is installed, code calling this method
* needs the {@code SecurityPermission} {@code printIdentity} to be granted,
* otherwise a {@code SecurityException} will be thrown.
- * </p>
- *
+ *
* @return a printable representation for this {@code Identity}.
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this method.
- * @since Android 1.0
*/
+ @Override
+ @SuppressWarnings("nls")
public String toString() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
- sm.checkSecurityAccess("printIdentity"); //$NON-NLS-1$
+ sm.checkSecurityAccess("printIdentity");
}
- String s = (this.name == null? "" : this.name);
+ String s = (this.name == null ? "" : this.name);
if (scope != null) {
- s += " [" + scope.getName() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
+ s += " [" + scope.getName() + "]";
}
return s;
}
diff --git a/libcore/security/src/main/java/java/security/IdentityScope.java b/libcore/security/src/main/java/java/security/IdentityScope.java
index 93729dc..60ab3e8c 100644
--- a/libcore/security/src/main/java/java/security/IdentityScope.java
+++ b/libcore/security/src/main/java/java/security/IdentityScope.java
@@ -15,29 +15,17 @@
* limitations under the License.
*/
-/**
-* @author Aleksei Y. Semenov
-* @version $Revision$
-*/
-
-// BEGIN android-note
-// Added Deprecated annotation.
-// END android-note
-
package java.security;
import java.util.Enumeration;
-import org.apache.harmony.security.SystemScope;
-
/**
* {@code IdentityScope} represents a scope for {@link Identity} objects.
- *
+ *
* @deprecated The functionality of this class has been replace by
* {@link Principal}, {@link KeyStore} and the {@code
* java.security.cert} package.
- * @since Android 1.0
*/
@Deprecated
public abstract class IdentityScope extends Identity {
@@ -49,8 +37,6 @@
/**
* Constructs a new instance of {@code IdentityScope}.
- *
- * @since Android 1.0
*/
protected IdentityScope() {
super();
@@ -59,10 +45,9 @@
/**
* Constructs a new instance of {@code IdentityScope} with the specified
* name.
- *
+ *
* @param name
* the name of this {@code IdentityScope}.
- * @since Android 1.0
*/
public IdentityScope(String name) {
super(name);
@@ -71,14 +56,13 @@
/**
* Constructs a new instance of {@code IdentityScope} with the specified
* name and the specified scope.
- *
+ *
* @param name
* the name of this {@code IdentityScope}.
* @param scope
* the scope of this {@code IdentityScope}.
* @throws KeyManagementException
* if an identity with the same key already exists.
- * @since Android 1.0
*/
public IdentityScope(String name, IdentityScope scope)
throws KeyManagementException {
@@ -87,9 +71,8 @@
/**
* Returns the system's scope.
- *
+ *
* @return the system's scope.
- * @since Android 1.0
*/
public static IdentityScope getSystemScope() {
/*
@@ -116,10 +99,9 @@
/**
* Sets the system's scope.
- *
+ *
* @param scope
* the scope to set.
- * @since Android 1.0
*/
protected static void setSystemScope(IdentityScope scope) {
SecurityManager sm = System.getSecurityManager();
@@ -131,21 +113,19 @@
/**
* Returns the number of {@code Identity} objects in this scope.
- *
+ *
* @return the number of {@code Identity} objects in this scope.
- * @since Android 1.0
*/
public abstract int size();
/**
* Returns the {@code Identity} with the specified name or {@code null} if
* no {@code Identity} with the specified name is present in this scope.
- *
+ *
* @param name
* the name of the {@code Identity} to be returned.
* @return the {@code Identity} with the specified name or {@code null} if
* not present.
- * @since Android 1.0
*/
public abstract Identity getIdentity(String name);
@@ -153,13 +133,12 @@
* Returns the {@code Identity} with the name of the specified principal or
* {@code null} if no {@code Identity} with the name of the specified
* principal is present in this scope.
- *
+ *
* @param principal
* the {@code Principal} whose name is used to lookup the {@code
* Identity} to be returned.
* @return the {@code Identity} with the specified name or {@code null} if
* not present.
- * @since Android 1.0
*/
public Identity getIdentity(Principal principal) {
return getIdentity(principal.getName());
@@ -169,36 +148,33 @@
* Returns the {@code Identity} which is associated with the specified key
* or {@code null} if no {@code Identity} associated with the specified key
* is present in this scope.
- *
+ *
* @param key
* the {@code PublicKey} of the {@code Identity} to be returned.
* @return the {@code Identity} associated with the specified key or {@code
* null} if not present.
- * @since Android 1.0
*/
public abstract Identity getIdentity(PublicKey key);
/**
* Adds an {@code Identity} to this {@code IdentityScope}.
- *
+ *
* @param identity
* the {@code Identity} to be added.
* @throws KeyManagementException
* if the specified {@code Identity} is invalid or an identity
* with the same key already exists.
- * @since Android 1.0
*/
public abstract void addIdentity(Identity identity)
throws KeyManagementException;
/**
* Removes an {@code Identity} from this {@code IdentityScope}.
- *
+ *
* @param identity
* the {@code Identity} to be removed.
* @throws KeyManagementException
* if the {@code Identity} is not present in this scope.
- * @since Android 1.0
*/
public abstract void removeIdentity(Identity identity)
throws KeyManagementException;
@@ -206,22 +182,21 @@
/**
* Returns an {@code Enumeration} over the {@code Identity} objects in this
* {@code IdentityScope}.
- *
+ *
* @return an {@code Enumeration} over the {@code Identity} objects in this
* {@code IdentityScope}.
- * @since Android 1.0
*/
public abstract Enumeration<Identity> identities();
/**
* Returns a string containing a concise, human-readable description of this
* {@code IdentityScope}.
- *
+ *
* @return a printable representation for this {@code IdentityScope}.
- * @since Android 1.0
*/
+ @Override
public String toString() {
- return new StringBuffer(super.toString())
+ return new StringBuilder(super.toString())
.append("[").append(size()).append("]").toString(); //$NON-NLS-1$ //$NON-NLS-2$
}
}
diff --git a/libcore/security/src/main/java/java/security/InvalidAlgorithmParameterException.java b/libcore/security/src/main/java/java/security/InvalidAlgorithmParameterException.java
index 0d8a607..26d9f97 100644
--- a/libcore/security/src/main/java/java/security/InvalidAlgorithmParameterException.java
+++ b/libcore/security/src/main/java/java/security/InvalidAlgorithmParameterException.java
@@ -15,31 +15,22 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
package java.security;
/**
* {@code InvalidAlgorithmParameterException} indicates the occurrence of
* invalid algorithm parameters.
- *
- * @since Android 1.0
*/
public class InvalidAlgorithmParameterException extends
GeneralSecurityException {
-
private static final long serialVersionUID = 2864672297499471472L;
/**
* Constructs a new instance of {@code InvalidAlgorithmParameterException}
* with the given message.
- *
+ *
* @param msg
* the detail message for this exception.
- * @since Android 1.0
*/
public InvalidAlgorithmParameterException(String msg) {
super(msg);
@@ -47,8 +38,6 @@
/**
* Constructs a new instance of {@code InvalidAlgorithmParameterException}.
- *
- * @since Android 1.0
*/
public InvalidAlgorithmParameterException() {
}
@@ -56,12 +45,11 @@
/**
* Constructs a new instance of {@code InvalidAlgorithmParameterException} with the
* given message and the cause.
- *
+ *
* @param message
* the detail message for this exception.
* @param cause
* the exception which is the cause for this exception.
- * @since Android 1.0
*/
public InvalidAlgorithmParameterException(String message, Throwable cause) {
super(message, cause);
@@ -70,10 +58,9 @@
/**
* Constructs a new instance of {@code InvalidAlgorithmParameterException}
* with the cause.
- *
+ *
* @param cause
* the exception which is the cause for this exception.
- * @since Android 1.0
*/
public InvalidAlgorithmParameterException(Throwable cause) {
super(cause);
diff --git a/libcore/security/src/main/java/java/security/InvalidKeyException.java b/libcore/security/src/main/java/java/security/InvalidKeyException.java
index 95d864e..f08fc51 100644
--- a/libcore/security/src/main/java/java/security/InvalidKeyException.java
+++ b/libcore/security/src/main/java/java/security/InvalidKeyException.java
@@ -15,18 +15,11 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
package java.security;
/**
* {@code InvalidKeyException} indicates exceptional conditions, caused by an
* invalid key.
- *
- * @since Android 1.0
*/
public class InvalidKeyException extends KeyException {
@@ -35,10 +28,9 @@
/**
* Constructs a new instance of {@code InvalidKeyException} with the given
* message.
- *
+ *
* @param msg
* the detail message for this exception.
- * @since Android 1.0
*/
public InvalidKeyException(String msg) {
super(msg);
@@ -46,8 +38,6 @@
/**
* Constructs a new instance of {@code InvalidKeyException}.
- *
- * @since Android 1.0
*/
public InvalidKeyException() {
}
@@ -55,12 +45,11 @@
/**
* Constructs a new instance of {@code InvalidKeyException} with the given
* message and the cause.
- *
+ *
* @param message
* the detail message for this exception.
* @param cause
* the exception which is the cause for this exception.
- * @since Android 1.0
*/
public InvalidKeyException(String message, Throwable cause) {
super(message, cause);
@@ -68,10 +57,9 @@
/**
* Constructs a new instance of {@code InvalidKeyException} with the cause.
- *
+ *
* @param cause
* the exception which is the cause for this exception.
- * @since Android 1.0
*/
public InvalidKeyException(Throwable cause) {
super(cause);
diff --git a/libcore/security/src/main/java/java/security/InvalidParameterException.java b/libcore/security/src/main/java/java/security/InvalidParameterException.java
index ac10448..6ad4645 100644
--- a/libcore/security/src/main/java/java/security/InvalidParameterException.java
+++ b/libcore/security/src/main/java/java/security/InvalidParameterException.java
@@ -15,18 +15,11 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
package java.security;
/**
* {@code InvalidParameterException} indicates exceptional conditions, caused by
* invalid parameters.
- *
- * @since Android 1.0
*/
public class InvalidParameterException extends IllegalArgumentException {
@@ -35,10 +28,9 @@
/**
* Constructs a new instance of {@code InvalidParameterException} with the
* given message.
- *
+ *
* @param msg
* the detail message for this exception.
- * @since Android 1.0
*/
public InvalidParameterException(String msg) {
super(msg);
@@ -46,8 +38,6 @@
/**
* Constructs a new instance of {@code InvalidParameterException}.
- *
- * @since Android 1.0
*/
public InvalidParameterException() {
}
diff --git a/libcore/security/src/main/java/java/security/Key.java b/libcore/security/src/main/java/java/security/Key.java
index 1359ab2..28d24ff 100644
--- a/libcore/security/src/main/java/java/security/Key.java
+++ b/libcore/security/src/main/java/java/security/Key.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
package java.security;
import java.io.Serializable;
@@ -29,14 +24,11 @@
*
* @see PublicKey
* @see PrivateKey
- * @since Android 1.0
*/
public interface Key extends Serializable {
/**
* The {@code serialVersionUID} to be compatible with JDK1.1.
- *
- * @since Android 1.0
*/
public static final long serialVersionUID = 6603384152749567654L;
@@ -46,7 +38,6 @@
*
* @return the name of the algorithm of this key or {@code null} if the
* algorithm is unknown.
- * @since Android 1.0
*/
public String getAlgorithm();
@@ -56,7 +47,6 @@
*
* @return the name of the format used to encode this key, or {@code null}
* if it can not be encoded.
- * @since Android 1.0
*/
public String getFormat();
@@ -66,7 +56,6 @@
*
* @return the encoded form of this key, or {@code null} if encoding is not
* supported by this key.
- * @since Android 1.0
*/
public byte[] getEncoded();
}
diff --git a/libcore/security/src/main/java/java/security/KeyException.java b/libcore/security/src/main/java/java/security/KeyException.java
index b01f75b..721c896 100644
--- a/libcore/security/src/main/java/java/security/KeyException.java
+++ b/libcore/security/src/main/java/java/security/KeyException.java
@@ -15,17 +15,10 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
package java.security;
/**
* {@code KeyException} is the common superclass of all key related exceptions.
- *
- * @since Android 1.0
*/
public class KeyException extends GeneralSecurityException {
@@ -33,10 +26,9 @@
/**
* Constructs a new instance of {@code KeyException} with the given message.
- *
+ *
* @param msg
* the detail message for this exception.
- * @since Android 1.0
*/
public KeyException(String msg) {
super(msg);
@@ -44,8 +36,6 @@
/**
* Constructs a new instance of {@code KeyException}.
- *
- * @since Android 1.0
*/
public KeyException() {
}
@@ -53,12 +43,11 @@
/**
* Constructs a new instance of {@code KeyException} with the given message
* and the cause.
- *
+ *
* @param message
* the detail message for this exception.
* @param cause
* the exception which is the cause for this exception.
- * @since Android 1.0
*/
public KeyException(String message, Throwable cause) {
super(message, cause);
@@ -66,10 +55,9 @@
/**
* Constructs a new instance of {@code KeyException} with the cause.
- *
+ *
* @param cause
* the exception which is the cause for this exception.
- * @since Android 1.0
*/
public KeyException(Throwable cause) {
super(cause);
diff --git a/libcore/security/src/main/java/java/security/KeyFactory.java b/libcore/security/src/main/java/java/security/KeyFactory.java
index 7c4966f..7484a31 100644
--- a/libcore/security/src/main/java/java/security/KeyFactory.java
+++ b/libcore/security/src/main/java/java/security/KeyFactory.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
package java.security;
import java.security.spec.InvalidKeySpecException;
@@ -33,8 +28,6 @@
* public and private key objects and convert keys between their external
* representation, that can be easily transported and their internal
* representation.
- *
- * @since Android 1.0
*/
public class KeyFactory {
// The service name.
@@ -63,7 +56,6 @@
* the provider.
* @param algorithm
* the algorithm to use.
- * @since Android 1.0
*/
protected KeyFactory(KeyFactorySpi keyFacSpi,
Provider provider,
@@ -83,7 +75,6 @@
* algorithm.
* @throws NoSuchAlgorithmException
* if no provider provides the requested algorithm.
- * @since Android 1.0
*/
public static KeyFactory getInstance(String algorithm)
throws NoSuchAlgorithmException {
@@ -112,16 +103,16 @@
* if the requested provider is not available.
* @throws IllegalArgumentException
* if {@code provider} is {@code null} or empty.
- * @since Android 1.0
*/
+ @SuppressWarnings("nls")
public static KeyFactory getInstance(String algorithm, String provider)
throws NoSuchAlgorithmException, NoSuchProviderException {
if ((provider == null) || (provider.length() == 0)) {
- throw new IllegalArgumentException(Messages.getString("security.02")); //$NON-NLS-1$
+ throw new IllegalArgumentException(Messages.getString("security.02"));
}
Provider p = Security.getProvider(provider);
if (p == null) {
- throw new NoSuchProviderException(Messages.getString("security.03", provider)); //$NON-NLS-1$ //$NON-NLS-2$
+ throw new NoSuchProviderException(Messages.getString("security.03", provider));
}
return getInstance(algorithm, p);
}
@@ -138,7 +129,6 @@
* algorithm from the specified provider.
* @throws NoSuchAlgorithmException
* if the provider does not provide the requested algorithm.
- * @since Android 1.0
*/
public static KeyFactory getInstance(String algorithm, Provider provider)
throws NoSuchAlgorithmException {
@@ -158,19 +148,17 @@
* Returns the provider associated with this {@code KeyFactory}.
*
* @return the provider associated with this {@code KeyFactory}.
- * @since Android 1.0
*/
public final Provider getProvider() {
return provider;
}
/**
- * Returns the name of the algorithm associated with this {@code KeyFactory}
- * .
+ * Returns the name of the algorithm associated with this {@code
+ * KeyFactory}.
*
- * @return the name of the algorithm associated with this {@code KeyFactory}
- * .
- * @since Android 1.0
+ * @return the name of the algorithm associated with this {@code
+ * KeyFactory}.
*/
public final String getAlgorithm() {
return algorithm;
@@ -185,7 +173,6 @@
* @return the public key
* @throws InvalidKeySpecException
* if the specified {@code keySpec} is invalid
- * @since Android 1.0
*/
public final PublicKey generatePublic(KeySpec keySpec)
throws InvalidKeySpecException {
@@ -201,7 +188,6 @@
* @return the private key.
* @throws InvalidKeySpecException
* if the specified {@code keySpec} is invalid.
- * @since Android 1.0
*/
public final PrivateKey generatePrivate(KeySpec keySpec)
throws InvalidKeySpecException {
@@ -219,7 +205,6 @@
* @throws InvalidKeySpecException
* if the key can not be processed, or the requested requested
* {@code KeySpec} is inappropriate for the given key.
- * @since Android 1.0
*/
public final <T extends KeySpec> T getKeySpec(Key key,
Class<T> keySpec)
@@ -236,7 +221,6 @@
* @throws InvalidKeyException
* if the specified key can not be translated by this key
* factory.
- * @since Android 1.0
*/
public final Key translateKey(Key key)
throws InvalidKeyException {
diff --git a/libcore/security/src/main/java/java/security/KeyFactorySpi.java b/libcore/security/src/main/java/java/security/KeyFactorySpi.java
index 7d3154e..0de00b2 100644
--- a/libcore/security/src/main/java/java/security/KeyFactorySpi.java
+++ b/libcore/security/src/main/java/java/security/KeyFactorySpi.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
package java.security;
import java.security.spec.InvalidKeySpecException;
@@ -30,7 +25,6 @@
* {@link KeyFactory}.
*
* @see KeyFactory
- * @since Android 1.0
*/
public abstract class KeyFactorySpi {
@@ -43,7 +37,6 @@
* @return the public key.
* @throws InvalidKeySpecException
* if the specified {@code keySpec} is invalid.
- * @since Android 1.0
*/
protected abstract PublicKey engineGeneratePublic(KeySpec keySpec)
throws InvalidKeySpecException;
@@ -57,7 +50,6 @@
* @return the private key.
* @throws InvalidKeySpecException
* if the specified {@code keySpec} is invalid.
- * @since Android 1.0
*/
protected abstract PrivateKey engineGeneratePrivate(KeySpec keySpec)
throws InvalidKeySpecException;
@@ -73,7 +65,6 @@
* @throws InvalidKeySpecException
* if the key can not be processed, or the requested requested
* {@code KeySpec} is inappropriate for the given key.
- * @since Android 1.0
*/
protected abstract <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec)
throws InvalidKeySpecException;
@@ -88,7 +79,6 @@
* @throws InvalidKeyException
* if the specified key can not be translated by this key
* factory.
- * @since Android 1.0
*/
protected abstract Key engineTranslateKey(Key key) throws InvalidKeyException;
diff --git a/libcore/security/src/main/java/java/security/KeyManagementException.java b/libcore/security/src/main/java/java/security/KeyManagementException.java
index 295ec03..00a5b3c 100644
--- a/libcore/security/src/main/java/java/security/KeyManagementException.java
+++ b/libcore/security/src/main/java/java/security/KeyManagementException.java
@@ -15,18 +15,11 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
package java.security;
/**
* {@code KeyManagementException} is a general exception, thrown to indicate an
* exception during processing an operation concerning key management.
- *
- * @since Android 1.0
*/
public class KeyManagementException extends KeyException {
@@ -35,10 +28,9 @@
/**
* Constructs a new instance of {@code KeyManagementException} with the
* given message.
- *
+ *
* @param msg
* the detail message for this exception.
- * @since Android 1.0
*/
public KeyManagementException(String msg) {
super(msg);
@@ -46,8 +38,6 @@
/**
* Constructs a new instance of {@code KeyManagementException}.
- *
- * @since Android 1.0
*/
public KeyManagementException() {
}
@@ -55,12 +45,11 @@
/**
* Constructs a new instance of {@code KeyManagementException} with the
* given message and the cause.
- *
+ *
* @param message
* the detail message for this exception.
* @param cause
* the exception which is the cause for this exception.
- * @since Android 1.0
*/
public KeyManagementException(String message, Throwable cause) {
super(message, cause);
@@ -69,13 +58,12 @@
/**
* Constructs a new instance of {@code KeyManagementException} with the
* cause.
- *
+ *
* @param cause
* the exception which is the cause for this exception.
- * @since Android 1.0
*/
public KeyManagementException(Throwable cause) {
super(cause);
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/KeyPair.java b/libcore/security/src/main/java/java/security/KeyPair.java
index 6399427..b86593b 100644
--- a/libcore/security/src/main/java/java/security/KeyPair.java
+++ b/libcore/security/src/main/java/java/security/KeyPair.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Vladimir N. Molotkov
-* @version $Revision$
-*/
-
package java.security;
import java.io.Serializable;
@@ -30,7 +25,6 @@
*
* @see PrivateKey
* @see PublicKey
- * @since Android 1.0
*/
public final class KeyPair implements Serializable {
@@ -41,12 +35,11 @@
/**
* Constructs a new instance of {@code KeyPair} with a public key and the
* corresponding private key.
- *
+ *
* @param publicKey
* the public key.
* @param privateKey
* the private key.
- * @since Android 1.0
*/
public KeyPair(PublicKey publicKey, PrivateKey privateKey) {
this.privateKey = privateKey;
@@ -55,9 +48,8 @@
/**
* Returns the private key.
- *
+ *
* @return the private key.
- * @since Android 1.0
*/
public PrivateKey getPrivate() {
return privateKey;
@@ -65,9 +57,8 @@
/**
* Returns the public key.
- *
+ *
* @return the public key.
- * @since Android 1.0
*/
public PublicKey getPublic() {
return publicKey;
diff --git a/libcore/security/src/main/java/java/security/KeyPairGenerator.java b/libcore/security/src/main/java/java/security/KeyPairGenerator.java
index 5682aa2..2a17e98 100644
--- a/libcore/security/src/main/java/java/security/KeyPairGenerator.java
+++ b/libcore/security/src/main/java/java/security/KeyPairGenerator.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
package java.security;
import java.security.spec.AlgorithmParameterSpec;
@@ -32,9 +27,8 @@
* {@code KeyPairGenerator} is an engine class which is capable of generating a
* private key and its related public key utilizing the algorithm it was
* initialized with.
- *
+ *
* @see KeyPairGeneratorSpi
- * @since Android 1.0
*/
public abstract class KeyPairGenerator extends KeyPairGeneratorSpi {
@@ -56,10 +50,9 @@
/**
* Constructs a new instance of {@code KeyPairGenerator} with the name of
* the algorithm to use.
- *
+ *
* @param algorithm
* the name of algorithm to use
- * @since Android 1.0
*/
protected KeyPairGenerator(String algorithm) {
this.algorithm = algorithm;
@@ -67,9 +60,8 @@
/**
* Returns the name of the algorithm of this {@code KeyPairGenerator}.
- *
+ *
* @return the name of the algorithm of this {@code KeyPairGenerator}
- * @since Android 1.0
*/
public String getAlgorithm() {
return algorithm;
@@ -86,7 +78,6 @@
* @throws NoSuchAlgorithmException if the specified algorithm is not available
* @throws NullPointerException
* if {@code algorithm} is {@code null}
- * @since Android 1.0
*/
public static KeyPairGenerator getInstance(String algorithm)
throws NoSuchAlgorithmException {
@@ -101,11 +92,10 @@
result.algorithm = algorithm;
result.provider = engine.provider;
return result;
- } else {
- result = new KeyPairGeneratorImpl((KeyPairGeneratorSpi) engine.spi,
- engine.provider, algorithm);
- return result;
}
+ result = new KeyPairGeneratorImpl((KeyPairGeneratorSpi) engine.spi,
+ engine.provider, algorithm);
+ return result;
}
}
@@ -123,7 +113,6 @@
* @throws NoSuchProviderException if the specified provider is not available
* @throws NullPointerException
* if {@code algorithm} is {@code null}
- * @since Android 1.0
*/
public static KeyPairGenerator getInstance(String algorithm, String provider)
throws NoSuchAlgorithmException, NoSuchProviderException {
@@ -151,7 +140,6 @@
* @throws NoSuchAlgorithmException if the specified algorithm is not available
* @throws NullPointerException
* if {@code algorithm} is {@code null}
- * @since Android 1.0
*/
public static KeyPairGenerator getInstance(String algorithm,
Provider provider) throws NoSuchAlgorithmException {
@@ -169,19 +157,17 @@
result.algorithm = algorithm;
result.provider = provider;
return result;
- } else {
- result = new KeyPairGeneratorImpl((KeyPairGeneratorSpi) engine.spi,
- provider, algorithm);
- return result;
}
+ result = new KeyPairGeneratorImpl((KeyPairGeneratorSpi) engine.spi,
+ provider, algorithm);
+ return result;
}
}
/**
* Returns the provider associated with this {@code KeyPairGenerator}.
- *
+ *
* @return the provider associated with this {@code KeyPairGenerator}
- * @since Android 1.0
*/
public final Provider getProvider() {
return provider;
@@ -191,10 +177,9 @@
* Initializes this {@code KeyPairGenerator} with the given key size. The
* default parameter set and a default {@code SecureRandom} instance will be
* used.
- *
+ *
* @param keysize
* the size of the key (number of bits)
- * @since Android 1.0
*/
public void initialize(int keysize) {
initialize(keysize, random);
@@ -204,12 +189,11 @@
* Initializes this {@code KeyPairGenerator} with the given {@code
* AlgorithmParameterSpec}. A default {@code SecureRandom} instance will be
* used.
- *
+ *
* @param param
* the parameters to use
* @throws InvalidAlgorithmParameterException
* if the specified parameters are not supported
- * @since Android 1.0
*/
public void initialize(AlgorithmParameterSpec param)
throws InvalidAlgorithmParameterException {
@@ -221,9 +205,8 @@
* is called.
* <p>
* This does exactly the same as {@link #generateKeyPair()}.
- *
+ *
* @return a new unique {@code KeyPair} each time this method is called
- * @since Android 1.0
*/
public final KeyPair genKeyPair() {
return generateKeyPair();
@@ -234,10 +217,10 @@
* is called.
* <p>
* This does exactly the same as {@link #genKeyPair()}.
- *
+ *
* @return a new unique {@code KeyPair} each time this method is called
- * @since Android 1.0
*/
+ @Override
public KeyPair generateKeyPair() {
return null;
}
@@ -245,28 +228,28 @@
/**
* Initializes this {@code KeyPairGenerator} with the given key size and the
* given {@code SecureRandom}. The default parameter set will be used.
- *
+ *
* @param keysize
* the key size
* @param random
* the source of randomness
- * @since Android 1.0
*/
+ @Override
public void initialize(int keysize, SecureRandom random) {
}
/**
* Initializes this {@code KeyPairGenerator} with the given {@code
* AlgorithmParameterSpec} and the given {@code SecureRandom}.
- *
+ *
* @param param
* the parameters to use
* @param random
* the source of randomness
* @throws InvalidAlgorithmParameterException
* if the specified parameters are not supported
- * @since Android 1.0
*/
+ @Override
public void initialize(AlgorithmParameterSpec param, SecureRandom random)
throws InvalidAlgorithmParameterException {
}
@@ -294,18 +277,21 @@
// implementation of initialize(int keysize, SecureRandom random)
// using corresponding spi initialize() method
+ @Override
public void initialize(int keysize, SecureRandom random) {
spiImpl.initialize(keysize, random);
}
// implementation of generateKeyPair()
// using corresponding spi generateKeyPair() method
+ @Override
public KeyPair generateKeyPair() {
return spiImpl.generateKeyPair();
}
// implementation of initialize(int keysize, SecureRandom random)
// using corresponding spi initialize() method
+ @Override
public void initialize(AlgorithmParameterSpec param, SecureRandom random)
throws InvalidAlgorithmParameterException {
spiImpl.initialize(param, random);
@@ -313,4 +299,4 @@
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/KeyPairGeneratorSpi.java b/libcore/security/src/main/java/java/security/KeyPairGeneratorSpi.java
index 272c305..e2e22c1 100644
--- a/libcore/security/src/main/java/java/security/KeyPairGeneratorSpi.java
+++ b/libcore/security/src/main/java/java/security/KeyPairGeneratorSpi.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
package java.security;
import java.security.spec.AlgorithmParameterSpec;
@@ -31,14 +26,10 @@
* definition for {@link KeyPairGenerator}.
*
* @see KeyPairGenerator
- * @since Android 1.0
*/
public abstract class KeyPairGeneratorSpi {
-
/**
* Constructs a new instance of {@code KeyPairGeneratorSpi}.
- *
- * @since Android 1.0
*/
public KeyPairGeneratorSpi() {
}
@@ -46,38 +37,35 @@
/**
* Computes and returns a new unique {@code KeyPair} each time this method
* is called.
- *
+ *
* @return a new unique {@code KeyPair} each time this method is called.
- * @since Android 1.0
*/
public abstract KeyPair generateKeyPair();
/**
* Initializes this {@code KeyPairGeneratorSpi} with the given key size and
* the given {@code SecureRandom}. The default parameter set will be used.
- *
+ *
* @param keysize
* the key size (number of bits).
* @param random
* the source of randomness.
- * @since Android 1.0
*/
public abstract void initialize(int keysize, SecureRandom random);
/**
* Initializes this {@code KeyPairGeneratorSpi} with the given {@code
* AlgorithmParameterSpec} and the given {@code SecureRandom}.
- *
+ *
* @param params
* the parameters to use.
* @param random
* the source of randomness.
* @throws InvalidAlgorithmParameterException
* if the specified parameters are not supported.
- * @since Android 1.0
*/
public void initialize(AlgorithmParameterSpec params, SecureRandom random)
throws InvalidAlgorithmParameterException {
throw new UnsupportedOperationException(Messages.getString("security.2E")); //$NON-NLS-1$
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/KeyRep.java b/libcore/security/src/main/java/java/security/KeyRep.java
index ec1d364..29ccd22 100644
--- a/libcore/security/src/main/java/java/security/KeyRep.java
+++ b/libcore/security/src/main/java/java/security/KeyRep.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Vladimir N. Molotkov
-* @version $Revision$
-*/
-
package java.security;
import java.io.IOException;
@@ -38,8 +33,6 @@
/**
* {@code KeyRep} is a standardized representation for serialized {@link Key}
* objects.
- *
- * @since Android 1.0
*/
public class KeyRep implements Serializable {
@@ -57,7 +50,7 @@
* Constructs a new instance of {@code KeyRep} with the specified arguments.
* The arguments should be obtained from the {@code Key} object that has to
* be serialized.
- *
+ *
* @param type
* the type of the key.
* @param algorithm
@@ -70,7 +63,6 @@
* @throws NullPointerException
* if {@code type, algorithm, format or encoded} is {@code null}
* .
- * @since Android 1.0
*/
public KeyRep(Type type,
String algorithm, String format, byte[] encoded) {
@@ -107,12 +99,11 @@
* initialized with a {@link X509EncodedKeySpec} using the encoded key
* bytes.
* </ul>
- *
+ *
* @return the resolved {@code Key} object.
* @throws ObjectStreamException
* if the {@code Type}|format combination is not recognized, or
* the resolution of any key parameter fails.
- * @since Android 1.0
*/
protected Object readResolve() throws ObjectStreamException {
switch (type) {
@@ -174,10 +165,8 @@
/**
* {@code Type} enumerates the supported key types.
- * @since Android 1.0
*/
public static enum Type {
-
/**
* Type for secret keys.
*/
diff --git a/libcore/security/src/main/java/java/security/KeyStore.java b/libcore/security/src/main/java/java/security/KeyStore.java
index 699a9df..02ac01d 100644
--- a/libcore/security/src/main/java/java/security/KeyStore.java
+++ b/libcore/security/src/main/java/java/security/KeyStore.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
package java.security;
import java.io.File;
@@ -29,6 +24,7 @@
import java.io.OutputStream;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Date;
import java.util.Enumeration;
@@ -46,14 +42,12 @@
* {@code KeyStore} is responsible for maintaining cryptographic keys and their
* owners.
* <p>
- * The type of the system key store can be changed by setting the {@code
+ * The type of the system key store can be changed by setting the {@code
* 'keystore.type'} property in the file named {@code
* JAVA_HOME/lib/security/java.security}.
- * </p>
- *
+ *
* @see Certificate
* @see PrivateKey
- * @since Android 1.0
*/
public class KeyStore {
@@ -88,14 +82,13 @@
/**
* Constructs a new instance of {@code KeyStore} with the given arguments.
- *
+ *
* @param keyStoreSpi
* the concrete key store.
* @param provider
* the provider.
* @param type
* the type of the {@code KeyStore} to be constructed.
- * @since Android 1.0
*/
protected KeyStore(KeyStoreSpi keyStoreSpi, Provider provider, String type) {
this.type = type;
@@ -118,7 +111,7 @@
/**
* Returns a new instance of {@code KeyStore} with the specified type.
- *
+ *
* @param type
* the type of the returned {@code KeyStore}.
* @return a new instance of {@code KeyStore} with the specified type.
@@ -128,7 +121,6 @@
* @throws NullPointerException
* if {@code type} is {@code null}.
* @see #getDefaultType
- * @since Android 1.0
*/
public static KeyStore getInstance(String type) throws KeyStoreException {
if (type == null) {
@@ -147,7 +139,7 @@
/**
* Returns a new instance of {@code KeyStore} from the specified provider
* with the given type.
- *
+ *
* @param type
* the type of the returned {@code KeyStore}.
* @param provider
@@ -161,8 +153,10 @@
* if the specified provider is not available.
* @throws IllegalArgumentException
* if {@code provider} is {@code null} or the empty string.
+ * @throws NullPointerException
+ * if {@code type} is {@code null} (instead of
+ * NoSuchAlgorithmException) as in 1.4 release
* @see #getDefaultType
- * @since Android 1.0
*/
public static KeyStore getInstance(String type, String provider)
throws KeyStoreException, NoSuchProviderException {
@@ -183,7 +177,7 @@
/**
* Returns a new instance of {@code KeyStore} from the specified provider
* with the given type.
- *
+ *
* @param type
* the type of the returned {@code KeyStore}.
* @param provider
@@ -195,8 +189,10 @@
* KeyStore}.
* @throws IllegalArgumentException
* if {@code provider} is {@code null} or the empty string.
+ * @throws NullPointerException
+ * if {@code type} is {@code null} (instead of
+ * NoSuchAlgorithmException) as in 1.4 release
* @see #getDefaultType
- * @since Android 1.0
*/
public static KeyStore getInstance(String type, Provider provider)
throws KeyStoreException {
@@ -225,10 +221,8 @@
* The default is specified in the {@code 'keystore.type'} property in the
* file named {@code JAVA_HOME/lib/security/java.security}. If this property
* is not set, {@code "jks"} will be used.
- * </p>
- *
+ *
* @return the default type for {@code KeyStore} instances
- * @since Android 1.0
*/
public static final String getDefaultType() {
String dt = AccessController.doPrivileged(
@@ -243,9 +237,8 @@
/**
* Returns the provider associated with this {@code KeyStore}.
- *
+ *
* @return the provider associated with this {@code KeyStore}.
- * @since Android 1.0
*/
public final Provider getProvider() {
return provider;
@@ -253,9 +246,8 @@
/**
* Returns the type of this {@code KeyStore}.
- *
+ *
* @return the type of this {@code KeyStore}.
- * @since Android 1.0
*/
public final String getType() {
return type;
@@ -264,7 +256,7 @@
/**
* Returns the key with the given alias, using the password to recover the
* key from the store.
- *
+ *
* @param alias
* the alias for the entry.
* @param password
@@ -277,7 +269,6 @@
* if the algorithm for recovering the key is not available.
* @throws UnrecoverableKeyException
* if the key can not be recovered.
- * @since Android 1.0
*/
public final Key getKey(String alias, char[] password)
throws KeyStoreException, NoSuchAlgorithmException,
@@ -292,14 +283,13 @@
/**
* Returns the certificate chain for the entry with the given alias.
- *
+ *
* @param alias
* the alias for the entry.
* @return the certificate chain for the entry with the given alias, or
* {@code null} if the specified alias is not bound to an entry.
* @throws KeyStoreException
* if this {@code KeyStore} is not initialized.
- * @since Android 1.0
*/
public final Certificate[] getCertificateChain(String alias)
throws KeyStoreException {
@@ -313,14 +303,13 @@
/**
* Returns the trusted certificate for the entry with the given alias.
- *
+ *
* @param alias
* the alias for the entry.
* @return the trusted certificate for the entry with the given alias, or
* {@code null} if the specified alias is not bound to an entry.
* @throws KeyStoreException
* if this {@code KeyStore} is not initialized.
- * @since Android 1.0
*/
public final Certificate getCertificate(String alias)
throws KeyStoreException {
@@ -334,14 +323,13 @@
/**
* Returns the creation date of the entry with the given alias.
- *
+ *
* @param alias
* the alias for the entry.
* @return the creation date, or {@code null} if the specified alias is not
* bound to an entry.
* @throws KeyStoreException
* if this {@code KeyStore} is not initialized.
- * @since Android 1.0
*/
public final Date getCreationDate(String alias) throws KeyStoreException {
if (!isInit) {
@@ -356,8 +344,7 @@
* Associates the given alias with the key, password and certificate chain.
* <p>
* If the specified alias already exists, it will be reassigned.
- * </p>
- *
+ *
* @param alias
* the alias for the key.
* @param key
@@ -371,7 +358,8 @@
* @throws IllegalArgumentException
* if {@code key} is a {@code PrivateKey} and {@code chain} does
* not contain any certificates.
- * @since Android 1.0
+ * @throws NullPointerException
+ * if {@code alias} is {@code null}.
*/
public final void setKeyEntry(String alias, Key key, char[] password,
Certificate[] chain) throws KeyStoreException {
@@ -394,13 +382,11 @@
* Associates the given alias with a key and a certificate chain.
* <p>
* If the specified alias already exists, it will be reassigned.
- * </p>
* <p>
* If this {@code KeyStore} is of type {@code "jks"}, {@code key} must be
* encoded conform to the PKS#8 standard as an
* {@link javax.crypto.EncryptedPrivateKeyInfo}.
- * </p>
- *
+ *
* @param alias
* the alias for the key.
* @param key
@@ -408,11 +394,13 @@
* @param chain
* the certificate chain.
* @throws KeyStoreException
- * if this {@code KeyStore} is not initialized.
+ * if this {@code KeyStore} is not initialized or if {@code key}
+ * is null.
* @throws IllegalArgumentException
* if {@code key} is a {@code PrivateKey} and {@code chain}
* does.
- * @since Android 1.0
+ * @throws NullPointerException
+ * if {@code alias} is {@code null}.
*/
public final void setKeyEntry(String alias, byte[] key, Certificate[] chain)
throws KeyStoreException {
@@ -428,8 +416,7 @@
* Associates the given alias with a certificate.
* <p>
* If the specified alias already exists, it will be reassigned.
- * </p>
- *
+ *
* @param alias
* the alias for the certificate.
* @param cert
@@ -438,7 +425,8 @@
* if this {@code KeyStore} is not initialized, or an existing
* alias is not associated to an entry containing a trusted
* certificate, or this method fails for any other reason.
- * @since Android 1.0
+ * @throws NullPointerException
+ * if {@code alias} is {@code null}.
*/
public final void setCertificateEntry(String alias, Certificate cert)
throws KeyStoreException {
@@ -453,32 +441,35 @@
/**
* Deletes the entry identified with the given alias from this {@code
* KeyStore}.
- *
+ *
* @param alias
* the alias for the entry.
* @throws KeyStoreException
* if this {@code KeyStore} is not initialized, or if the entry
* can not be deleted.
- * @since Android 1.0
+ * @throws NullPointerException
+ * if {@code alias} is {@code null}.
*/
public final void deleteEntry(String alias) throws KeyStoreException {
- // BEGIN android-changed
if (!isInit) {
+ // BEGIN android-changed
throwNotInitialized();
+ // END android-changed
}
- // END android-changed
+ if (alias == null) {
+ throw new NullPointerException(Messages.getString("security.3F")); //$NON-NLS-1$
+ }
implSpi.engineDeleteEntry(alias);
}
/**
* Returns an {@code Enumeration} over all alias names stored in this
* {@code KeyStore}.
- *
+ *
* @return an {@code Enumeration} over all alias names stored in this
* {@code KeyStore}.
* @throws KeyStoreException
* if this {@code KeyStore} is not initialized.
- * @since Android 1.0
*/
public final Enumeration<String> aliases() throws KeyStoreException {
if (!isInit) {
@@ -491,13 +482,14 @@
/**
* Indicates whether the given alias is present in this {@code KeyStore}.
- *
+ *
* @param alias
* the alias of an entry.
* @return {@code true} if the alias exists, {@code false} otherwise.
* @throws KeyStoreException
* if this {@code KeyStore} is not initialized.
- * @since Android 1.0
+ * @throws NullPointerException
+ * if {@code alias} is {@code null}.
*/
public final boolean containsAlias(String alias) throws KeyStoreException {
if (!isInit) {
@@ -513,11 +505,10 @@
/**
* Returns the number of entries stored in this {@code KeyStore}.
- *
+ *
* @return the number of entries stored in this {@code KeyStore}.
* @throws KeyStoreException
* if this {@code KeyStore} is not initialized.
- * @since Android 1.0
*/
public final int size() throws KeyStoreException {
if (!isInit) {
@@ -531,56 +522,63 @@
/**
* Indicates whether the specified alias is associated with either a
* {@link PrivateKeyEntry} or a {@link SecretKeyEntry}.
- *
+ *
* @param alias
* the alias of an entry.
* @return {@code true} if the given alias is associated with a key entry.
* @throws KeyStoreException
* if this {@code KeyStore} is not initialized.
- * @since Android 1.0
+ * @throws NullPointerException
+ * if {@code alias} is {@code null}.
*/
public final boolean isKeyEntry(String alias) throws KeyStoreException {
- // BEGIN android-changed
if (!isInit) {
+ // BEGIN android-changed
throwNotInitialized();
+ // END android-changed
}
- // END android-changed
+ if (alias == null) {
+ throw new NullPointerException(Messages.getString("security.3F")); //$NON-NLS-1$
+ }
return implSpi.engineIsKeyEntry(alias);
}
/**
* Indicates whether the specified alias is associated with a
* {@link TrustedCertificateEntry}.
- *
+ *
* @param alias
* the alias of an entry.
* @return {@code true} if the given alias is associated with a certificate
* entry.
* @throws KeyStoreException
* if this {@code KeyStore} is not initialized.
- * @since Android 1.0
+ * @throws NullPointerException
+ * if {@code alias} is {@code null}.
*/
public final boolean isCertificateEntry(String alias)
throws KeyStoreException {
- // BEGIN android-changed
if (!isInit) {
+ // BEGIN android-changed
throwNotInitialized();
+ // END android-changed
}
- // END android-changed
+ if (alias == null) {
+ throw new NullPointerException(Messages.getString("security.3F")); //$NON-NLS-1$
+ }
return implSpi.engineIsCertificateEntry(alias);
}
/**
* Returns the alias associated with the first entry whose certificate
* matches the specified certificate.
- *
+ *
* @param cert
* the certificate to find the associated entry's alias for.
* @return the alias or {@code null} if no entry with the specified
* certificate can be found.
* @throws KeyStoreException
* if this {@code KeyStore} is not initialized.
- * @since Android 1.0
*/
public final String getCertificateAlias(Certificate cert)
throws KeyStoreException {
@@ -596,7 +594,7 @@
* Writes this {@code KeyStore} to the specified {@code OutputStream}. The
* data written to the {@code OutputStream} is protected by the specified
* password.
- *
+ *
* @param stream
* the {@code OutputStream} to write the store's data to.
* @param password
@@ -610,7 +608,6 @@
* @throws CertificateException
* if an exception occurred while storing the certificates of
* this {@code KeyStore}.
- * @since Android 1.0
*/
public final void store(OutputStream stream, char[] password)
throws KeyStoreException, IOException, NoSuchAlgorithmException,
@@ -620,23 +617,15 @@
throwNotInitialized();
// END android-changed
}
- // BEGIN android-removed
- // copied from a newer version of harmony
- // Just delegate stream and password to implSpi
- // if (stream == null) {
- // throw new IOException(Messages.getString("security.51")); //$NON-NLS-1$
- // }
- // if (password == null) {
- // throw new IOException(Messages.getString("security.50")); //$NON-NLS-1$
- // }
- // END android-removed
+
+ //Just delegate stream and password to implSpi
implSpi.engineStore(stream, password);
}
/**
* Stores this {@code KeyStore} using the specified {@code
* LoadStoreParameter}.
- *
+ *
* @param param
* the {@code LoadStoreParameter} that specifies how to store
* this {@code KeyStore}, maybe {@code null}.
@@ -651,7 +640,6 @@
* this {@code KeyStore}.
* @throws IllegalArgumentException
* if the given {@link LoadStoreParameter} is not recognized.
- * @since Android 1.0
*/
public final void store(LoadStoreParameter param) throws KeyStoreException,
IOException, NoSuchAlgorithmException, CertificateException {
@@ -669,7 +657,7 @@
* {@code KeyStore} or to initialize a {@code KeyStore} which does not rely
* on an {@code InputStream}. This {@code KeyStore} utilizes the given
* password to verify the stored data.
- *
+ *
* @param stream
* the {@code InputStream} to load this {@code KeyStore}'s data
* from or {@code null}.
@@ -682,7 +670,6 @@
* @throws CertificateException
* if an exception occurred while loading the certificates of
* this {@code KeyStore}.
- * @since Android 1.0
*/
public final void load(InputStream stream, char[] password)
throws IOException, NoSuchAlgorithmException, CertificateException {
@@ -693,7 +680,7 @@
/**
* Loads this {@code KeyStore} using the specified {@code
* LoadStoreParameter}.
- *
+ *
* @param param
* the {@code LoadStoreParameter} that specifies how to load this
* {@code KeyStore}, maybe {@code null}.
@@ -706,7 +693,6 @@
* this {@code KeyStore}.
* @throws IllegalArgumentException
* if the given {@link LoadStoreParameter} is not recognized.
- * @since Android 1.0
*/
public final void load(LoadStoreParameter param) throws IOException,
NoSuchAlgorithmException, CertificateException {
@@ -717,7 +703,7 @@
/**
* Returns the {@code Entry} with the given alias, using the specified
* {@code ProtectionParameter}.
- *
+ *
* @param alias
* the alias of the requested entry.
* @param param
@@ -731,7 +717,8 @@
* if the entry can not be recovered.
* @throws KeyStoreException
* if this {@code KeyStore} is not initialized.
- * @since Android 1.0
+ * @throws NullPointerException
+ * if {@code alias} is {@code null}.
*/
public final Entry getEntry(String alias, ProtectionParameter param)
throws NoSuchAlgorithmException, UnrecoverableEntryException,
@@ -753,8 +740,7 @@
* specified {@code ProtectionParameter}.
* <p>
* If the specified alias already exists, it will be reassigned.
- * </p>
- *
+ *
* @param alias
* the alias for the entry.
* @param entry
@@ -763,7 +749,9 @@
* the {@code ProtectionParameter} to protect the entry.
* @throws KeyStoreException
* if this {@code KeyStore} is not initialized.
- * @since Android 1.0
+ * @throws NullPointerException
+ * if {@code alias} is {@code null} or {@code entry} is {@code
+ * null}.
*/
public final void setEntry(String alias, Entry entry,
ProtectionParameter param) throws KeyStoreException {
@@ -784,7 +772,7 @@
/**
* Indicates whether the entry for the given alias is assignable to the
* provided {@code Class}.
- *
+ *
* @param alias
* the alias for the entry.
* @param entryClass
@@ -793,7 +781,6 @@
* the specified {@code entryClass}.
* @throws KeyStoreException
* if this {@code KeyStore} is not initialized.
- * @since Android 1.0
*/
public final boolean entryInstanceOf(String alias,
Class<? extends KeyStore.Entry> entryClass)
@@ -815,25 +802,20 @@
/**
* {@code Builder} is used to construct new instances of {@code KeyStore}.
- *
- * @since Android 1.0
*/
public abstract static class Builder {
/**
* Constructs a new instance of {@code Builder}.
- *
- * @since Android 1.0
*/
protected Builder() {
}
/**
* Returns the {@code KeyStore} created by this {@code Builder}.
- *
+ *
* @return the {@code KeyStore} created by this {@code Builder}.
* @throws KeyStoreException
* if an error occurred during construction.
- * @since Android 1.0
*/
public abstract KeyStore getKeyStore() throws KeyStoreException;
@@ -841,7 +823,7 @@
* Returns the {@code ProtectionParameter} to be used when a {@code
* Entry} with the specified alias is requested. Before this method is
* invoked, {@link #getKeyStore()} must be called.
- *
+ *
* @param alias
* the alias for the entry.
* @return the {@code ProtectionParameter} to be used when a {@code
@@ -854,18 +836,14 @@
* invocation of this method.
* @throws NullPointerException
* if {@code alias} is {@code null}.
- * @since Android 1.0
*/
public abstract ProtectionParameter getProtectionParameter(String alias)
throws KeyStoreException;
- // BEGIN android-note
- // renamed parameter
- // END android-note
/**
* Returns a new {@code Builder} that holds the given {@code KeyStore}
* and the given {@code ProtectionParameter}.
- *
+ *
* @param keyStore
* the {@code KeyStore} to be held.
* @param protectionParameter
@@ -878,7 +856,6 @@
* {@code null}.
* @throws IllegalArgumentException
* if the given {@code KeyStore} is not initialized.
- * @since Android 1.0
*/
public static Builder newInstance(KeyStore keyStore,
ProtectionParameter protectionParameter) {
@@ -903,8 +880,7 @@
* If {@code provider} is {@code null}, all installed providers are
* searched, otherwise the key store from the specified provider is
* used.
- * </p>
- *
+ *
* @param type
* the type of the {@code KeyStore} to be constructed.
* @param provider
@@ -926,7 +902,6 @@
* {@code PasswordProtection} or {@code
* CallbackHandlerProtection}, {@code file} is not a file or
* does not exist at all.
- * @since Android 1.0
*/
public static Builder newInstance(String type, Provider provider,
File file, ProtectionParameter protectionParameter) {
@@ -965,8 +940,7 @@
* If {@code provider} is {@code null}, all installed providers are
* searched, otherwise the key store from the specified provider is
* used.
- * </p>
- *
+ *
* @param type
* the type of the {@code KeyStore} to be constructed.
* @param provider
@@ -985,7 +959,6 @@
* {@code PasswordProtection} or {@code
* CallbackHandlerProtection}, {@code file} is not a file or
* does not exist at all.
- * @since Android 1.0
*/
public static Builder newInstance(String type, Provider provider,
ProtectionParameter protectionParameter) {
@@ -1062,6 +1035,7 @@
//
// Result KeyStore object is returned.
//
+ @Override
public synchronized KeyStore getKeyStore() throws KeyStoreException {
// If KeyStore was created but in final block some exception was
// thrown
@@ -1121,8 +1095,7 @@
isGetKeyStore = true;
- keyStore = ks;
- return keyStore;
+ return ks;
} catch (KeyStoreException e) {
// Store exception
throw lastException = e;
@@ -1139,6 +1112,7 @@
// Return: ProtectionParameter to get Entry which was saved in
// KeyStore with defined alias
//
+ @Override
public synchronized ProtectionParameter getProtectionParameter(
String alias) throws KeyStoreException {
if (alias == null) {
@@ -1151,13 +1125,8 @@
}
}
- // BEGIN android-note
- // Added "static" to the class declaration below.
- // END android-note
/*
* Implementation of LoadStoreParameter interface
- *
- * @author Vera Petrashkova
*/
private static class TmpLSParameter implements LoadStoreParameter {
@@ -1166,6 +1135,7 @@
/**
* Creates TmpLoadStoreParameter object
+ * @param protPar protection parameter
*/
public TmpLSParameter(ProtectionParameter protPar) {
this.protPar = protPar;
@@ -1183,8 +1153,6 @@
/**
* {@code CallbackHandlerProtection} is a {@code ProtectionParameter} that
* encapsulates a {@link CallbackHandler}.
- *
- * @since Android 1.0
*/
public static class CallbackHandlerProtection implements
ProtectionParameter {
@@ -1194,12 +1162,11 @@
/**
* Constructs a new instance of {@code CallbackHandlerProtection} with
* the {@code CallbackHandler}.
- *
+ *
* @param handler
* the {@code CallbackHandler}.
* @throws NullPointerException
* if {@code handler} is {@code null}.
- * @since Android 1.0
*/
public CallbackHandlerProtection(CallbackHandler handler) {
if (handler == null) {
@@ -1210,9 +1177,8 @@
/**
* Returns the {@code CallbackHandler}.
- *
+ *
* @return the {@code CallbackHandler}.
- * @since Android 1.0
*/
public CallbackHandler getCallbackHandler() {
return callbackHandler;
@@ -1222,8 +1188,6 @@
/**
* {@code Entry} is the common marker interface for a {@code KeyStore}
* entry.
- *
- * @since Android 1.0
*/
public static interface Entry {
}
@@ -1231,19 +1195,17 @@
/**
* {@code LoadStoreParameter} represents a parameter that specifies how a
* {@code KeyStore} can be loaded and stored.
- *
+ *
* @see KeyStore#load(LoadStoreParameter)
* @see KeyStore#store(LoadStoreParameter)
- * @since Android 1.0
*/
public static interface LoadStoreParameter {
/**
* Returns the {@code ProtectionParameter} which is used to protect data
* in the {@code KeyStore}.
- *
+ *
* @return the {@code ProtectionParameter} which is used to protect data
* in the {@code KeyStore}, maybe {@code null}.
- * @since Android 1.0
*/
public ProtectionParameter getProtectionParameter();
}
@@ -1251,8 +1213,6 @@
/**
* {@code PasswordProtection} is a {@code ProtectionParameter} that protects
* a {@code KeyStore} using a password.
- *
- * @since Android 1.0
*/
public static class PasswordProtection implements ProtectionParameter,
Destroyable {
@@ -1266,27 +1226,22 @@
* Constructs a new instance of {@code PasswordProtection} with a
* password. A copy of the password is stored in the new {@code
* PasswordProtection} object.
- *
+ *
* @param password
* the password, maybe {@code null}.
- * @since Android 1.0
*/
public PasswordProtection(char[] password) {
- // BEGIN android-changed
- // copied from a newer version of harmony
- if (password != null) {
- this.password = password.clone();
- }
- // END android-changed
+ if (password != null) {
+ this.password = password.clone();
+ }
}
/**
* Returns the password.
- *
+ *
* @return the password.
* @throws IllegalStateException
* if the password has been destroyed.
- * @since Android 1.0
*/
public synchronized char[] getPassword() {
if (isDestroyed) {
@@ -1297,10 +1252,9 @@
/**
* Destroys / invalidates the password.
- *
+ *
* @throws DestroyFailedException
* if the password could not be invalidated.
- * @since Android 1.0
*/
public synchronized void destroy() throws DestroyFailedException {
isDestroyed = true;
@@ -1312,10 +1266,9 @@
/**
* Indicates whether the password is invalidated.
- *
+ *
* @return {@code true} if the password is invalidated, {@code false}
* otherwise.
- * @since Android 1.0
*/
public synchronized boolean isDestroyed() {
return isDestroyed;
@@ -1326,8 +1279,6 @@
* {@code ProtectionParameter} is a marker interface for protection
* parameters. A protection parameter is used to protect the content of a
* {@code KeyStore}.
- *
- * @since Android 1.0
*/
public static interface ProtectionParameter {
}
@@ -1335,8 +1286,6 @@
/**
* {@code PrivateKeyEntry} represents a {@code KeyStore} entry that
* holds a private key.
- *
- * @since Android 1.0
*/
public static final class PrivateKeyEntry implements Entry {
// Store Certificate chain
@@ -1348,7 +1297,7 @@
/**
* Constructs a new instance of {@code PrivateKeyEntry} with the given
* {@code PrivateKey} and the provided certificate chain.
- *
+ *
* @param privateKey
* the private key.
* @param chain
@@ -1361,7 +1310,6 @@
* private key does not match the algorithm of the public
* key of the first certificate or the certificates are not
* all of the same type.
- * @since Android 1.0
*/
public PrivateKeyEntry(PrivateKey privateKey, Certificate[] chain) {
if (privateKey == null) {
@@ -1389,18 +1337,29 @@
}
}
// clone chain - this.chain = (Certificate[])chain.clone();
- // BEGIN android-changed
- this.chain = new Certificate[chain.length];
- // END android-changed
+ boolean isAllX509Certificates = true;
+ // assert chain length > 0
+ for(Certificate cert: chain){
+ if(!(cert instanceof X509Certificate)){
+ isAllX509Certificates = false;
+ break;
+ }
+ }
+
+ if(isAllX509Certificates){
+ this.chain = new X509Certificate[chain.length];
+ }
+ else{
+ this.chain = new Certificate[chain.length];
+ }
System.arraycopy(chain, 0, this.chain, 0, chain.length);
this.privateKey = privateKey;
}
/**
* Returns the private key.
- *
+ *
* @return the private key.
- * @since Android 1.0
*/
public PrivateKey getPrivateKey() {
return privateKey;
@@ -1408,22 +1367,17 @@
/**
* Returns the certificate chain.
- *
+ *
* @return the certificate chain.
- * @since Android 1.0
*/
public Certificate[] getCertificateChain() {
- // BEGIN android-changed
- // copied from a newer version of harmony
return chain.clone();
- // END android-changed
}
/**
* Returns the certificate corresponding to the private key.
- *
+ *
* @return the certificate corresponding to the private key.
- * @since Android 1.0
*/
public Certificate getCertificate() {
return chain[0];
@@ -1432,12 +1386,12 @@
/**
* Returns a string containing a concise, human-readable description of
* this {@code PrivateKeyEntry}.
- *
+ *
* @return a printable representation for this {@code PrivateKeyEntry}.
- * @since Android 1.0
*/
+ @Override
public String toString() {
- StringBuffer sb = new StringBuffer(
+ StringBuilder sb = new StringBuilder(
"PrivateKeyEntry: number of elements in certificate chain is "); //$NON-NLS-1$
sb.append(Integer.toString(chain.length));
sb.append("\n"); //$NON-NLS-1$
@@ -1452,8 +1406,6 @@
/**
* {@code SecretKeyEntry} represents a {@code KeyStore} entry that
* holds a secret key.
- *
- * @since Android 1.0
*/
public static final class SecretKeyEntry implements Entry {
@@ -1463,12 +1415,11 @@
/**
* Constructs a new instance of {@code SecretKeyEntry} with the given
* {@code SecretKey}.
- *
+ *
* @param secretKey
* the secret key.
* @throws NullPointerException
* if {@code secretKey} is {@code null}.
- * @since Android 1.0
*/
public SecretKeyEntry(SecretKey secretKey) {
if (secretKey == null) {
@@ -1479,9 +1430,8 @@
/**
* Returns the secret key.
- *
+ *
* @return the secret key.
- * @since Android 1.0
*/
public SecretKey getSecretKey() {
return secretKey;
@@ -1490,13 +1440,13 @@
/**
* Returns a string containing a concise, human-readable description of
* this {@code SecretKeyEntry}.
- *
+ *
* @return a printable representation for this {@code
* SecretKeyEntry}.
- * @since Android 1.0
*/
+ @Override
public String toString() {
- StringBuffer sb = new StringBuffer("SecretKeyEntry: algorithm - "); //$NON-NLS-1$
+ StringBuilder sb = new StringBuilder("SecretKeyEntry: algorithm - "); //$NON-NLS-1$
sb.append(secretKey.getAlgorithm());
return sb.toString();
}
@@ -1505,8 +1455,6 @@
/**
* {@code TrustedCertificateEntry} represents a {@code KeyStore} entry that
* holds a trusted certificate.
- *
- * @since Android 1.0
*/
public static final class TrustedCertificateEntry implements Entry {
@@ -1516,12 +1464,11 @@
/**
* Constructs a new instance of {@code TrustedCertificateEntry} with the
* given {@code Certificate}.
- *
+ *
* @param trustCertificate
* the trusted certificate.
* @throws NullPointerException
* if {@code trustCertificate} is {@code null}.
- * @since Android 1.0
*/
public TrustedCertificateEntry(Certificate trustCertificate) {
if (trustCertificate == null) {
@@ -1532,9 +1479,8 @@
/**
* Returns the trusted certificate.
- *
+ *
* @return the trusted certificate.
- * @since Android 1.0
*/
public Certificate getTrustedCertificate() {
return trustCertificate;
@@ -1543,11 +1489,11 @@
/**
* Returns a string containing a concise, human-readable description of
* this {@code TrustedCertificateEntry}.
- *
+ *
* @return a printable representation for this {@code
* TrustedCertificateEntry}.
- * @since Android 1.0
*/
+ @Override
public String toString() {
return "Trusted certificate entry:\n" + trustCertificate; //$NON-NLS-1$
}
diff --git a/libcore/security/src/main/java/java/security/KeyStoreException.java b/libcore/security/src/main/java/java/security/KeyStoreException.java
index 7c697f7..4327f7f 100644
--- a/libcore/security/src/main/java/java/security/KeyStoreException.java
+++ b/libcore/security/src/main/java/java/security/KeyStoreException.java
@@ -15,18 +15,12 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
package java.security;
/**
* {@code KeyStoreException} is a general {@code KeyStore} exception.
*
* @see KeyStore
- * @since Android 1.0
*/
public class KeyStoreException extends GeneralSecurityException {
@@ -35,10 +29,9 @@
/**
* Constructs a new instance of {@code KeyStoreException} with the
* given message.
- *
+ *
* @param msg
* the detail message for this exception.
- * @since Android 1.0
*/
public KeyStoreException(String msg) {
super(msg);
@@ -46,8 +39,6 @@
/**
* Constructs a new instance of {@code KeyStoreException}.
- *
- * @since Android 1.0
*/
public KeyStoreException() {
}
@@ -55,12 +46,11 @@
/**
* Constructs a new instance of {@code KeyStoreException} with the
* given message and the cause.
- *
+ *
* @param message
* the detail message for this exception.
* @param cause
* the exception which is the cause for this exception.
- * @since Android 1.0
*/
public KeyStoreException(String message, Throwable cause) {
super(message, cause);
@@ -69,10 +59,9 @@
/**
* Constructs a new instance of {@code KeyStoreException} with the
* cause.
- *
+ *
* @param cause
* the exception which is the cause for this exception.
- * @since Android 1.0
*/
public KeyStoreException(Throwable cause) {
super(cause);
diff --git a/libcore/security/src/main/java/java/security/KeyStoreSpi.java b/libcore/security/src/main/java/java/security/KeyStoreSpi.java
index b02f264..e884123 100644
--- a/libcore/security/src/main/java/java/security/KeyStoreSpi.java
+++ b/libcore/security/src/main/java/java/security/KeyStoreSpi.java
@@ -33,16 +33,15 @@
/**
* {@code KeyStoreSpi} is the Service Provider Interface (SPI) definition for
* {@link KeyStore}.
- *
+ *
* @see KeyStore
- * @since Android 1.0
*/
public abstract class KeyStoreSpi {
/**
* Returns the key with the given alias, using the password to recover the
* key from the store.
- *
+ *
* @param alias
* the alias for the entry.
* @param password
@@ -53,41 +52,37 @@
* if the algorithm for recovering the key is not available.
* @throws UnrecoverableKeyException
* if the key can not be recovered.
- * @since Android 1.0
*/
public abstract Key engineGetKey(String alias, char[] password)
throws NoSuchAlgorithmException, UnrecoverableKeyException;
/**
* Returns the certificate chain for the entry with the given alias.
- *
+ *
* @param alias
* the alias for the entry
* @return the certificate chain for the entry with the given alias, or
* {@code null} if the specified alias is not bound to an entry.
- * @since Android 1.0
*/
public abstract Certificate[] engineGetCertificateChain(String alias);
/**
* Returns the trusted certificate for the entry with the given alias.
- *
+ *
* @param alias
* the alias for the entry.
* @return the trusted certificate for the entry with the given alias, or
* {@code null} if the specified alias is not bound to an entry.
- * @since Android 1.0
*/
public abstract Certificate engineGetCertificate(String alias);
/**
* Returns the creation date of the entry with the given alias.
- *
+ *
* @param alias
* the alias for the entry.
* @return the creation date, or {@code null} if the specified alias is not
* bound to an entry.
- * @since Android 1.0
*/
public abstract Date engineGetCreationDate(String alias);
@@ -95,8 +90,7 @@
* Associates the given alias with the key, password and certificate chain.
* <p>
* If the specified alias already exists, it will be reassigned.
- * </p>
- *
+ *
* @param alias
* the alias for the key.
* @param key
@@ -111,7 +105,6 @@
* @throws IllegalArgumentException
* if {@code key} is a {@code PrivateKey} and {@code chain} does
* not contain any certificates.
- * @since Android 1.0
*/
public abstract void engineSetKeyEntry(String alias, Key key,
char[] password, Certificate[] chain) throws KeyStoreException;
@@ -120,8 +113,7 @@
* Associates the given alias with a key and a certificate chain.
* <p>
* If the specified alias already exists, it will be reassigned.
- * </p>
- *
+ *
* @param alias
* the alias for the key.
* @param key
@@ -133,7 +125,6 @@
* @throws IllegalArgumentException
* if {@code key} is a {@code PrivateKey} and {@code chain}
* does.
- * @since Android 1.0
*/
public abstract void engineSetKeyEntry(String alias, byte[] key,
Certificate[] chain) throws KeyStoreException;
@@ -142,8 +133,7 @@
* Associates the given alias with a certificate.
* <p>
* If the specified alias already exists, it will be reassigned.
- * </p>
- *
+ *
* @param alias
* the alias for the certificate.
* @param cert
@@ -152,7 +142,6 @@
* if an existing alias is not associated to an entry containing
* a trusted certificate, or this method fails for any other
* reason.
- * @since Android 1.0
*/
public abstract void engineSetCertificateEntry(String alias,
Certificate cert) throws KeyStoreException;
@@ -160,12 +149,11 @@
/**
* Deletes the entry identified with the given alias from this {@code
* KeyStoreSpi}.
- *
+ *
* @param alias
* the alias for the entry.
* @throws KeyStoreException
* if the entry can not be deleted.
- * @since Android 1.0
*/
public abstract void engineDeleteEntry(String alias)
throws KeyStoreException;
@@ -173,63 +161,57 @@
/**
* Returns an {@code Enumeration} over all alias names stored in this
* {@code KeyStoreSpi}.
- *
+ *
* @return an {@code Enumeration} over all alias names stored in this
* {@code KeyStoreSpi}.
- * @since Android 1.0
*/
public abstract Enumeration<String> engineAliases();
/**
* Indicates whether the given alias is present in this {@code KeyStoreSpi}.
- *
+ *
* @param alias
* the alias of an entry.
* @return {@code true} if the alias exists, {@code false} otherwise.
- * @since Android 1.0
*/
public abstract boolean engineContainsAlias(String alias);
/**
* Returns the number of entries stored in this {@code KeyStoreSpi}.
- *
+ *
* @return the number of entries stored in this {@code KeyStoreSpi}.
- * @since Android 1.0
*/
public abstract int engineSize();
/**
* Indicates whether the specified alias is associated with either a
* {@link KeyStore.PrivateKeyEntry} or a {@link KeyStore.SecretKeyEntry}.
- *
+ *
* @param alias
* the alias of an entry.
* @return {@code true} if the given alias is associated with a key entry.
- * @since Android 1.0
*/
public abstract boolean engineIsKeyEntry(String alias);
/**
* Indicates whether the specified alias is associated with a
* {@link KeyStore.TrustedCertificateEntry}.
- *
+ *
* @param alias
* the alias of an entry.
* @return {@code true} if the given alias is associated with a certificate
* entry.
- * @since Android 1.0
*/
public abstract boolean engineIsCertificateEntry(String alias);
/**
* Returns the alias associated with the first entry whose certificate
* matches the specified certificate.
- *
+ *
* @param cert
* the certificate to find the associated entry's alias for.
* @return the alias or {@code null} if no entry with the specified
* certificate can be found.
- * @since Android 1.0
*/
public abstract String engineGetCertificateAlias(Certificate cert);
@@ -237,7 +219,7 @@
* Writes this {@code KeyStoreSpi} to the specified {@code OutputStream}.
* The data written to the {@code OutputStream} is protected by the
* specified password.
- *
+ *
* @param stream
* the {@code OutputStream} to write the store's data to.
* @param password
@@ -249,7 +231,6 @@
* @throws CertificateException
* if the an exception occurred while storing the certificates
* of this code {@code KeyStoreSpi}.
- * @since Android 1.0
*/
public abstract void engineStore(OutputStream stream, char[] password)
throws IOException, NoSuchAlgorithmException, CertificateException;
@@ -257,7 +238,7 @@
/**
* Stores this {@code KeyStoreSpi} using the specified {@code
* LoadStoreParameter}.
- *
+ *
* @param param
* the {@code LoadStoreParameter} that specifies how to store
* this {@code KeyStoreSpi}, maybe {@code null}.
@@ -271,7 +252,6 @@
* @throws IllegalArgumentException
* if the given {@link KeyStore.LoadStoreParameter} is not
* recognized.
- * @since Android 1.0
*/
public void engineStore(KeyStore.LoadStoreParameter param)
throws IOException, NoSuchAlgorithmException, CertificateException {
@@ -281,7 +261,7 @@
/**
* Loads this {@code KeyStoreSpi} from the given {@code InputStream}.
* Utilizes the given password to verify the stored data.
- *
+ *
* @param stream
* the {@code InputStream} to load this {@code KeyStoreSpi}'s
* data from.
@@ -294,7 +274,6 @@
* @throws CertificateException
* if the an exception occurred while loading the certificates
* of this code {@code KeyStoreSpi}.
- * @since Android 1.0
*/
public abstract void engineLoad(InputStream stream, char[] password)
throws IOException, NoSuchAlgorithmException, CertificateException;
@@ -302,7 +281,7 @@
/**
* Loads this {@code KeyStoreSpi} using the specified {@code
* LoadStoreParameter}.
- *
+ *
* @param param
* the {@code LoadStoreParameter} that specifies how to load this
* {@code KeyStoreSpi}, maybe {@code null}.
@@ -316,7 +295,6 @@
* @throws IllegalArgumentException
* if the given {@link KeyStore.LoadStoreParameter} is not
* recognized.
- * @since Android 1.0
*/
public void engineLoad(KeyStore.LoadStoreParameter param)
throws IOException, NoSuchAlgorithmException, CertificateException {
@@ -351,7 +329,7 @@
/**
* Returns the {@code Entry} with the given alias, using the specified
* {@code ProtectionParameter}.
- *
+ *
* @param alias
* the alias of the requested entry.
* @param protParam
@@ -365,7 +343,6 @@
* if the entry can not be recovered.
* @throws KeyStoreException
* if this operation fails
- * @since Android 1.0
*/
public KeyStore.Entry engineGetEntry(String alias,
KeyStore.ProtectionParameter protParam) throws KeyStoreException,
@@ -417,8 +394,7 @@
* specified {@code ProtectionParameter}.
* <p>
* If the specified alias already exists, it will be reassigned.
- * </p>
- *
+ *
* @param alias
* the alias for the entry.
* @param entry
@@ -427,7 +403,6 @@
* the {@code ProtectionParameter} to protect the entry.
* @throws KeyStoreException
* if this operation fails.
- * @since Android 1.0
*/
public void engineSetEntry(String alias, KeyStore.Entry entry,
KeyStore.ProtectionParameter protParam) throws KeyStoreException {
@@ -486,14 +461,13 @@
/**
* Indicates whether the entry for the given alias is assignable to the
* provided {@code Class}.
- *
+ *
* @param alias
* the alias for the entry.
* @param entryClass
* the type of the entry.
* @return {@code true} if the {@code Entry} for the alias is assignable to
* the specified {@code entryClass}.
- * @since Android 1.0
*/
public boolean engineEntryInstanceOf(String alias,
Class<? extends KeyStore.Entry> entryClass) {
diff --git a/libcore/security/src/main/java/java/security/MessageDigest.java b/libcore/security/src/main/java/java/security/MessageDigest.java
index 97cbdcc..cb8fc08 100644
--- a/libcore/security/src/main/java/java/security/MessageDigest.java
+++ b/libcore/security/src/main/java/java/security/MessageDigest.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
package java.security;
import java.nio.ByteBuffer;
@@ -31,12 +26,11 @@
* {@code MessageDigest} is an engine class which is capable of generating one
* way hash values for arbitrary input, utilizing the algorithm it was
* initialized with.
- *
+ *
* @see MessageDigestSpi
- * @since Android 1.0
*/
public abstract class MessageDigest extends MessageDigestSpi {
-
+
// The service name
private static final String SERVICE = "MessageDigest"; //$NON-NLS-1$
@@ -55,7 +49,6 @@
*
* @param algorithm
* the name of algorithm to use
- * @since Android 1.0
*/
protected MessageDigest(String algorithm) {
this.algorithm = algorithm;
@@ -73,7 +66,6 @@
* if the specified algorithm is not available
* @throws NullPointerException
* if {@code algorithm} is {@code null}
- * @since Android 1.0
*/
public static MessageDigest getInstance(String algorithm)
throws NoSuchAlgorithmException {
@@ -88,11 +80,9 @@
result.algorithm = algorithm;
result.provider = engine.provider;
return result;
- } else {
- result = new MessageDigestImpl((MessageDigestSpi) engine.spi,
- engine.provider, algorithm);
- return result;
}
+ return new MessageDigestImpl((MessageDigestSpi) engine.spi,
+ engine.provider, algorithm);
}
}
@@ -112,16 +102,17 @@
* if the specified provider is not available
* @throws NullPointerException
* if {@code algorithm} is {@code null}
- * @since Android 1.0
*/
public static MessageDigest getInstance(String algorithm, String provider)
throws NoSuchAlgorithmException, NoSuchProviderException {
if ((provider == null) || (provider.length() == 0)) {
- throw new IllegalArgumentException(Messages.getString("security.02")); //$NON-NLS-1$
+ throw new IllegalArgumentException(Messages
+ .getString("security.02")); //$NON-NLS-1$
}
Provider p = Security.getProvider(provider);
if (p == null) {
- throw new NoSuchProviderException(Messages.getString("security.03", provider)); //$NON-NLS-1$
+ throw new NoSuchProviderException(Messages.getString(
+ "security.03", provider)); //$NON-NLS-1$
}
return getInstance(algorithm, p);
}
@@ -140,12 +131,12 @@
* if the specified algorithm is not available
* @throws NullPointerException
* if {@code algorithm} is {@code null}
- * @since Android 1.0
*/
public static MessageDigest getInstance(String algorithm, Provider provider)
throws NoSuchAlgorithmException {
if (provider == null) {
- throw new IllegalArgumentException(Messages.getString("security.04")); //$NON-NLS-1$
+ throw new IllegalArgumentException(Messages
+ .getString("security.04")); //$NON-NLS-1$
}
if (algorithm == null) {
throw new NullPointerException(Messages.getString("security.01")); //$NON-NLS-1$
@@ -158,19 +149,16 @@
result.algorithm = algorithm;
result.provider = provider;
return result;
- } else {
- result = new MessageDigestImpl((MessageDigestSpi) engine.spi,
- provider, algorithm);
- return result;
}
+ result = new MessageDigestImpl((MessageDigestSpi) engine.spi,
+ provider, algorithm);
+ return result;
}
}
/**
* Puts this {@code MessageDigest} back in an initial state, such that it is
* ready to compute a one way hash value.
- *
- * @since Android 1.0
*/
public void reset() {
engineReset();
@@ -200,11 +188,10 @@
* @throws IllegalArgumentException
* if {@code offset} or {@code len} are not valid in respect to
* {@code input}
- * @since Android 1.0
*/
public void update(byte[] input, int offset, int len) {
if (input == null ||
- // offset < 0 || len < 0 ||
+ // offset < 0 || len < 0 ||
// checks for negative values are commented out intentionally
// see HARMONY-1120 for details
(long) offset + (long) len > input.length) {
@@ -221,7 +208,6 @@
* the {@code byte} array
* @throws NullPointerException
* if {@code input} is {@code null}
- * @since Android 1.0
*/
public void update(byte[] input) {
if (input == null) {
@@ -259,11 +245,10 @@
* if {@code offset} or {@code len} are not valid in respect to
* {@code buf}
* @see #reset()
- * @since Android 1.0
*/
public int digest(byte[] buf, int offset, int len) throws DigestException {
if (buf == null ||
- // offset < 0 || len < 0 ||
+ // offset < 0 || len < 0 ||
// checks for negative values are commented out intentionally
// see HARMONY-1148 for details
(long) offset + (long) len > buf.length) {
@@ -282,7 +267,6 @@
* the {@code byte} array
* @return the computed one way hash value
* @see #reset()
- * @since Android 1.0
*/
public byte[] digest(byte[] input) {
update(input);
@@ -294,8 +278,8 @@
* {@code MessageDigest} including the name of its algorithm.
*
* @return a printable representation for this {@code MessageDigest}
- * @since Android 1.0
*/
+ @Override
public String toString() {
return "MESSAGE DIGEST " + algorithm; //$NON-NLS-1$
}
@@ -309,7 +293,6 @@
* @param digestb
* the second digest to be compared
* @return {@code true} if the two hashes are equal, {@code false} otherwise
- * @since Android 1.0
*/
public static boolean isEqual(byte[] digesta, byte[] digestb) {
if (digesta.length != digestb.length) {
@@ -327,7 +310,6 @@
* Returns the name of the algorithm of this {@code MessageDigest}.
*
* @return the name of the algorithm of this {@code MessageDigest}
- * @since Android 1.0
*/
public final String getAlgorithm() {
return algorithm;
@@ -337,7 +319,6 @@
* Returns the provider associated with this {@code MessageDigest}.
*
* @return the provider associated with this {@code MessageDigest}
- * @since Android 1.0
*/
public final Provider getProvider() {
return provider;
@@ -349,7 +330,6 @@
* {@code 0} is returned.
*
* @return the digest length in bytes, or {@code 0}
- * @since Android 1.0
*/
public final int getDigestLength() {
int l = engineGetDigestLength();
@@ -367,12 +347,12 @@
}
}
+ @Override
public Object clone() throws CloneNotSupportedException {
if (this instanceof Cloneable) {
return super.clone();
- } else {
- throw new CloneNotSupportedException();
}
+ throw new CloneNotSupportedException();
}
/**
@@ -380,7 +360,6 @@
*
* @param input
* the {@code ByteBuffer}
- * @since Android 1.0
*/
public final void update(ByteBuffer input) {
engineUpdate(input);
@@ -392,7 +371,7 @@
*
*/
private static class MessageDigestImpl extends MessageDigest {
-
+
// MessageDigestSpi implementation
private MessageDigestSpi spiImpl;
@@ -405,38 +384,44 @@
}
// engineReset() implementation
+ @Override
protected void engineReset() {
spiImpl.engineReset();
}
// engineDigest() implementation
+ @Override
protected byte[] engineDigest() {
return spiImpl.engineDigest();
}
// engineGetDigestLength() implementation
+ @Override
protected int engineGetDigestLength() {
return spiImpl.engineGetDigestLength();
}
// engineUpdate() implementation
+ @Override
protected void engineUpdate(byte arg0) {
spiImpl.engineUpdate(arg0);
}
// engineUpdate() implementation
+ @Override
protected void engineUpdate(byte[] arg0, int arg1, int arg2) {
spiImpl.engineUpdate(arg0, arg1, arg2);
}
// Returns a clone if the spiImpl is cloneable
+ @Override
public Object clone() throws CloneNotSupportedException {
if (spiImpl instanceof Cloneable) {
MessageDigestSpi spi = (MessageDigestSpi) spiImpl.clone();
return new MessageDigestImpl(spi, getProvider(), getAlgorithm());
- } else {
- throw new CloneNotSupportedException();
}
+
+ throw new CloneNotSupportedException();
}
}
}
diff --git a/libcore/security/src/main/java/java/security/MessageDigestSpi.java b/libcore/security/src/main/java/java/security/MessageDigestSpi.java
index ae5ed32..52ad3cd 100644
--- a/libcore/security/src/main/java/java/security/MessageDigestSpi.java
+++ b/libcore/security/src/main/java/java/security/MessageDigestSpi.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
package java.security;
import java.nio.ByteBuffer;
@@ -33,7 +28,6 @@
* a fingerprint for a stream of bytes.
*
* @see MessageDigest
- * @since Android 1.0
*/
public abstract class MessageDigestSpi {
@@ -42,7 +36,6 @@
* implement this function {@code 0} is returned.
*
* @return the digest length in bytes, or {@code 0}.
- * @since Android 1.0
*/
protected int engineGetDigestLength() {
return 0;
@@ -54,10 +47,9 @@
* @param input
* the {@code byte} to update this {@code MessageDigestSpi} with.
* @see #engineReset()
- * @since Android 1.0
*/
protected abstract void engineUpdate(byte input);
-
+
/**
* Updates this {@code MessageDigestSpi} using the given {@code byte[]}.
*
@@ -70,7 +62,6 @@
* @throws IllegalArgumentException
* if {@code offset} or {@code len} are not valid in respect to
* {@code input}.
- * @since Android 1.0
*/
protected abstract void engineUpdate(byte[] input, int offset, int len);
@@ -79,7 +70,6 @@
*
* @param input
* the {@code ByteBuffer}.
- * @since Android 1.0
*/
protected void engineUpdate(ByteBuffer input) {
if (!input.hasRemaining()) {
@@ -107,7 +97,6 @@
*
* @return the computed one way hash value.
* @see #engineReset()
- * @since Android 1.0
*/
protected abstract byte[] engineDigest();
@@ -129,7 +118,6 @@
* if {@code offset} or {@code len} are not valid in respect to
* {@code buf}.
* @see #engineReset()
- * @since Android 1.0
*/
protected int engineDigest(byte[] buf, int offset, int len)
throws DigestException {
@@ -156,11 +144,10 @@
/**
* Puts this {@code MessageDigestSpi} back in an initial state, such that it
* is ready to compute a one way hash value.
- *
- * @since Android 1.0
*/
protected abstract void engineReset();
+ @Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
diff --git a/libcore/security/src/main/java/java/security/NoSuchAlgorithmException.java b/libcore/security/src/main/java/java/security/NoSuchAlgorithmException.java
index 3324076..8ef2e3f 100644
--- a/libcore/security/src/main/java/java/security/NoSuchAlgorithmException.java
+++ b/libcore/security/src/main/java/java/security/NoSuchAlgorithmException.java
@@ -15,18 +15,11 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
package java.security;
/**
* {@code NoSuchAlgorithmException} indicates that a requested algorithm could
* not be found.
- *
- * @since Android 1.0
*/
public class NoSuchAlgorithmException extends GeneralSecurityException {
@@ -35,10 +28,9 @@
/**
* Constructs a new instance of {@code NoSuchAlgorithmException} with the
* given message.
- *
+ *
* @param msg
* the detail message for this exception.
- * @since Android 1.0
*/
public NoSuchAlgorithmException(String msg) {
super(msg);
@@ -46,8 +38,6 @@
/**
* Constructs a new instance of {@code NoSuchAlgorithmException}.
- *
- * @since Android 1.0
*/
public NoSuchAlgorithmException() {
}
@@ -55,12 +45,11 @@
/**
* Constructs a new instance of {@code NoSuchAlgorithmException} with the
* given message and the cause.
- *
+ *
* @param message
* the detail message for this exception.
* @param cause
* the exception which is the cause for this exception.
- * @since Android 1.0
*/
public NoSuchAlgorithmException(String message, Throwable cause) {
super(message, cause);
@@ -69,10 +58,9 @@
/**
* Constructs a new instance of {@code NoSuchAlgorithmException} with the
* cause.
- *
+ *
* @param cause
* the exception which is the cause for this exception.
- * @since Android 1.0
*/
public NoSuchAlgorithmException(Throwable cause) {
super(cause);
diff --git a/libcore/security/src/main/java/java/security/NoSuchProviderException.java b/libcore/security/src/main/java/java/security/NoSuchProviderException.java
index f016ce6..57cda40 100644
--- a/libcore/security/src/main/java/java/security/NoSuchProviderException.java
+++ b/libcore/security/src/main/java/java/security/NoSuchProviderException.java
@@ -15,18 +15,11 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
package java.security;
/**
* {@code NoSuchProviderException} indicates that a requested security provider
* could not be found.
- *
- * @since Android 1.0
*/
public class NoSuchProviderException extends GeneralSecurityException {
@@ -35,10 +28,9 @@
/**
* Constructs a new instance of {@code NoSuchProviderException} with the
* given message.
- *
+ *
* @param msg
* the detail message for this exception.
- * @since Android 1.0
*/
public NoSuchProviderException(String msg) {
super(msg);
@@ -46,8 +38,6 @@
/**
* Constructs a new instance of {@code NoSuchProviderException}.
- *
- * @since Android 1.0
*/
public NoSuchProviderException() {
}
diff --git a/libcore/security/src/main/java/java/security/Permission.java b/libcore/security/src/main/java/java/security/Permission.java
index 93e769c..26bdfcd 100644
--- a/libcore/security/src/main/java/java/security/Permission.java
+++ b/libcore/security/src/main/java/java/security/Permission.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Alexey V. Varlamov
-* @version $Revision$
-*/
-
package java.security;
import java.io.Serializable;
@@ -29,8 +24,6 @@
* participate in the access control security framework around
* {@link AccessController} and {@link AccessControlContext}. A permission
* constitutes of a name and associated actions.
- *
- * @since Android 1.0
*/
public abstract class Permission implements Guard, Serializable {
@@ -45,46 +38,44 @@
* <p>
* The {@link #implies(Permission)} method should be used for making access
* control checks.
- * </p>
- *
+ *
* @param obj
* object to be compared for equality with this {@code
* Permission}.
* @return {@code true} if the specified object is equal to this {@code
* Permission}, otherwise {@code false}.
- * @since Android 1.0
*/
+ @Override
public abstract boolean equals(Object obj);
/**
* Returns the hash code value for this {@code Permission}. Returns the same
* hash code for {@code Permission}s that are equal to each other as
* required by the general contract of {@link Object#hashCode}.
- *
+ *
* @return the hash code value for this {@code Permission}.
* @see Object#equals(Object)
* @see Permission#equals(Object)
- * @since Android 1.0
*/
+ @Override
public abstract int hashCode();
/**
* Returns a comma separated string identifying the actions associated with
* this permission. The returned actions are in canonical form. For example:
- *
+ *
* <pre>
- * sp0 = new SocketPermission("www.google.com", "connect,resolve")
- * sp1 = new SocketPermission("www.google.com", "resolve,connect")
+ * sp0 = new SocketPermission("www.example.com", "connect,resolve")
+ * sp1 = new SocketPermission("www.example.com", "resolve,connect")
* sp0.getActions().equals(sp1.getActions()) //yields true
* </pre>
- *
+ *
* Both permissions return "connect,resolve" (in that order) if {@code
* #getActions()} is invoked. Returns an empty String, if no actions are
* associated with this permission.
- *
+ *
* @return the actions associated with this permission or an empty string if
* no actions are associated with this permission.
- * @since Android 1.0
*/
public abstract String getActions();
@@ -92,21 +83,19 @@
* Indicates whether the specified permission is implied by this permission.
* The {@link AccessController} uses this method to check whether permission
* protected access is allowed with the present policy.
- *
+ *
* @param permission
* the permission to check against this permission.
* @return {@code true} if the specified permission is implied by this
* permission, {@code false} otherwise.
- * @since Android 1.0
*/
public abstract boolean implies(Permission permission);
/**
* Constructs a new instance of {@code Permission} with its name.
- *
+ *
* @param name
* the name of the permission.
- * @since Android 1.0
*/
public Permission(String name) {
this.name = name;
@@ -114,9 +103,8 @@
/**
* Returns the name of this permission.
- *
+ *
* @return the name of this permission.
- * @since Android 1.0
*/
public final String getName() {
return name;
@@ -126,7 +114,7 @@
* Invokes {@link SecurityManager#checkPermission(Permission)} with this
* permission as its argument. This method implements the {@link Guard}
* interface.
- *
+ *
* @param obj
* as specified in {@link Guard#checkGuard(Object)} but ignored
* in this implementation.
@@ -134,7 +122,6 @@
* if this permission is not granted.
* @see Guard
* @see SecurityManager#checkPermission(Permission)
- * @since Android 1.0
*/
public void checkGuard(Object obj) throws SecurityException {
SecurityManager sm = System.getSecurityManager();
@@ -150,11 +137,9 @@
* <p>
* Subclasses may override this method to return an appropriate collection
* for the specific permissions they implement.
- * </p>
- *
+ *
* @return an empty {@link PermissionCollection} or {@code null} if any
* permission collection can be used.
- * @since Android 1.0
*/
public PermissionCollection newPermissionCollection() {
return null;
@@ -163,10 +148,10 @@
/**
* Returns a string containing a concise, human-readable description of the
* this {@code Permission} including its name and its actions.
- *
+ *
* @return a printable representation for this {@code Permission}.
- * @since Android 1.0
*/
+ @Override
public String toString() {
String actions = getActions();
actions = (actions == null || actions.length() == 0) ? "" : " " //$NON-NLS-1$ //$NON-NLS-2$
diff --git a/libcore/security/src/main/java/java/security/PermissionCollection.java b/libcore/security/src/main/java/java/security/PermissionCollection.java
index 2502123..56b6cd0 100644
--- a/libcore/security/src/main/java/java/security/PermissionCollection.java
+++ b/libcore/security/src/main/java/java/security/PermissionCollection.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Alexey V. Varlamov
-* @version $Revision$
-*/
-
package java.security;
import java.io.Serializable;
@@ -37,12 +32,8 @@
* method returns {@code null}, then a {@code PermissionCollection} of any type
* can be used. If a collection is returned, it must be used for holding several
* permissions of the particular type.
- * </p>
* <p>
* Subclasses must be implemented thread save.
- * </p>
- *
- * @since Android 1.0
*/
public abstract class PermissionCollection implements Serializable {
@@ -57,7 +48,6 @@
* the {@code Permission} to add.
* @throws IllegalStateException
* if the collection is read only.
- * @since Android 1.0
*/
public abstract void add(Permission permission);
@@ -66,7 +56,6 @@
* {@code PermissionCollection}.
*
* @return an enumeration over all {@link Permission}s.
- * @since Android 1.0
*/
public abstract Enumeration<Permission> elements();
@@ -78,7 +67,6 @@
* the permission to check.
* @return {@code true} if the given permission is implied by the
* permissions in this collection, {@code false} otherwise.
- * @since Android 1.0
*/
public abstract boolean implies(Permission permission);
@@ -88,7 +76,6 @@
*
* @return {@code true} if the receiver is read only, {@code false} if new
* elements can still be added to this {@code PermissionCollection}.
- * @since Android 1.0
*/
public boolean isReadOnly() {
return readOnly;
@@ -97,8 +84,6 @@
/**
* Marks this {@code PermissionCollection} as read only, so that no new
* permissions can be added to it.
- *
- * @since Android 1.0
*/
public void setReadOnly() {
readOnly = true;
@@ -109,11 +94,11 @@
* {@code PermissionCollection}.
*
* @return a printable representation for this {@code PermissionCollection}.
- * @since Android 1.0
*/
+ @Override
public String toString() {
- List elist = new ArrayList(100);
- Enumeration elenum = elements();
+ List<String> elist = new ArrayList<String>(100);
+ Enumeration<Permission> elenum = elements();
String superStr = super.toString();
int totalLength = superStr.length() + 5;
if (elenum != null) {
@@ -125,12 +110,11 @@
}
int esize = elist.size();
totalLength += esize * 4;
- //FIXME StringBuffer --> StringBuilder
- StringBuffer result = new StringBuffer(totalLength).append(superStr)
+ StringBuilder result = new StringBuilder(totalLength).append(superStr)
.append(" ("); //$NON-NLS-1$
for (int i = 0; i < esize; i++) {
- result.append("\n ").append(elist.get(i).toString()); //$NON-NLS-1$
+ result.append("\n ").append(elist.get(i).toString()); //$NON-NLS-1$
}
- return result.append("\n)").toString(); //$NON-NLS-1$
+ return result.append("\n)\n").toString(); //$NON-NLS-1$
}
}
diff --git a/libcore/security/src/main/java/java/security/Permissions.java b/libcore/security/src/main/java/java/security/Permissions.java
index b9b13c6..e8d3375 100644
--- a/libcore/security/src/main/java/java/security/Permissions.java
+++ b/libcore/security/src/main/java/java/security/Permissions.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Alexey V. Varlamov
-* @version $Revision$
-*/
-
package java.security;
import java.io.IOException;
@@ -44,8 +39,6 @@
* {@link Permission#newPermissionCollection()}. For permissions which do not
* provide a dedicated {@code PermissionCollection}, a default permission
* collection, based on a hash table, will be used.
- *
- * @since Android 1.0
*/
public final class Permissions extends PermissionCollection implements
Serializable {
@@ -65,7 +58,7 @@
* Adds the given {@code Permission} to this heterogeneous {@code
* PermissionCollection}. The {@code permission} is stored in its
* appropriate {@code PermissionCollection}.
- *
+ *
* @param permission
* the {@code Permission} to be added.
* @throws SecurityException
@@ -73,7 +66,6 @@
* {@code true}.
* @throws NullPointerException
* if {@code permission} is {@code null}.
- * @since Android 1.0
*/
public void add(Permission permission) {
if (isReadOnly()) {
@@ -223,9 +215,10 @@
Map perms = (Map)fields.get("perms", null); //$NON-NLS-1$
klasses = new HashMap();
synchronized (klasses) {
- for (Iterator iter = perms.keySet().iterator(); iter.hasNext();) {
- Class key = (Class)iter.next();
- PermissionCollection pc = (PermissionCollection)perms.get(key);
+ for (Iterator iter = perms.entrySet().iterator(); iter.hasNext();) {
+ Map.Entry entry = (Map.Entry) iter.next();
+ Class key = (Class) entry.getKey();
+ PermissionCollection pc = (PermissionCollection) entry.getValue();
if (key != pc.elements().nextElement().getClass()) {
throw new InvalidObjectException(Messages.getString("security.22")); //$NON-NLS-1$
}
diff --git a/libcore/security/src/main/java/java/security/PermissionsHash.java b/libcore/security/src/main/java/java/security/PermissionsHash.java
index 69d2b07..4c9e0c9 100644
--- a/libcore/security/src/main/java/java/security/PermissionsHash.java
+++ b/libcore/security/src/main/java/java/security/PermissionsHash.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Alexey V. Varlamov
-* @version $Revision$
-*/
-
package java.security;
import java.util.Enumeration;
@@ -30,28 +25,21 @@
/**
* A default {@code PermissionCollection} implementation that uses a hashtable.
* Each hashtable entry stores a Permission object as both the key and the
- * value. <br>
+ * value.
+ * <p>
* This {@code PermissionCollection} is intended for storing "neutral"
- * permissions which do not require special collection. </br>
- *
- * @since Android 1.0
+ * permissions which do not require special collection.
*/
final class PermissionsHash extends PermissionCollection {
- /**
- * @com.intel.drl.spec_ref
- */
private static final long serialVersionUID = -8491988220802933440L;
- /**
- * @com.intel.drl.spec_ref
- */
private final Hashtable perms = new Hashtable();
/**
* Adds the argument to the collection.
- *
+ *
* @param permission
* the permission to add to the collection.
*/
@@ -61,8 +49,7 @@
/**
* Returns an enumeration of the permissions in the receiver.
- *
- *
+ *
* @return Enumeration the permissions in the receiver.
*/
public Enumeration elements() {
@@ -72,8 +59,7 @@
/**
* Indicates whether the argument permission is implied by the permissions
* contained in the receiver.
- *
- *
+ *
* @return boolean <code>true</code> if the argument permission is implied
* by the permissions in the receiver, and <code>false</code> if
* it is not.
diff --git a/libcore/security/src/main/java/java/security/Policy.java b/libcore/security/src/main/java/java/security/Policy.java
index 21b13b0..d5719a3 100644
--- a/libcore/security/src/main/java/java/security/Policy.java
+++ b/libcore/security/src/main/java/java/security/Policy.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Alexey V. Varlamov
-* @version $Revision$
-*/
-
package java.security;
import java.util.Enumeration;
@@ -36,12 +31,8 @@
* The system policy can be changed by setting the {@code 'policy.provider'}
* property in the file named {@code JAVA_HOME/lib/security/java.security} to
* the fully qualified class name of the desired {@code Policy}.
- * </p>
* <p>
* Only one instance of a {@code Policy} is active at any time.
- * </p>
- *
- * @since Android 1.0
*/
public abstract class Policy {
@@ -68,20 +59,16 @@
* domain (i.e. system classes). System classes are always given
* full permissions (i.e. AllPermission). This can not be changed by
* installing a new policy.
- * </p>
- *
+ *
* @param cs
* the {@code CodeSource} to compute the permissions for.
* @return the permissions that are granted to the specified {@code
* CodeSource}.
- * @since Android 1.0
*/
public abstract PermissionCollection getPermissions(CodeSource cs);
/**
* Reloads the policy configuration for this {@code Policy} instance.
- *
- * @since Android 1.0
*/
public abstract void refresh();
@@ -94,13 +81,11 @@
* system domain (i.e. system classes). System classes are always
* given full permissions (i.e. AllPermission). This can not be changed by
* installing a new policy.
- * </p>
- *
+ *
* @param domain
* the {@code ProtectionDomain} to compute the permissions for.
* @return the permissions that are granted to the specified {@code
* CodeSource}.
- * @since Android 1.0
*/
public PermissionCollection getPermissions(ProtectionDomain domain) {
if (domain != null) {
@@ -112,7 +97,7 @@
/**
* Indicates whether the specified {@code Permission} is implied by the
* {@code PermissionCollection} of the specified {@code ProtectionDomain}.
- *
+ *
* @param domain
* the {@code ProtectionDomain} for which the permission should
* be granted.
@@ -121,7 +106,6 @@
* verified.
* @return {@code true} if the {@code Permission} is implied by the {@code
* ProtectionDomain}, {@code false} otherwise.
- * @since Android 1.0
*/
public boolean implies(ProtectionDomain domain, Permission permission) {
if (domain != null) {
@@ -130,8 +114,8 @@
if (total == null) {
total = inherent;
} else if (inherent != null) {
- for (Enumeration en = inherent.elements(); en.hasMoreElements();) {
- total.add((Permission)en.nextElement());
+ for (Enumeration<Permission> en = inherent.elements(); en.hasMoreElements();) {
+ total.add(en.nextElement());
}
}
if (total != null && total.implies(permission)) {
@@ -149,13 +133,11 @@
* If a {@code SecurityManager} is installed, code calling this method needs
* the {@code SecurityPermission} {@code getPolicy} to be granted, otherwise
* a {@code SecurityException} will be thrown.
- * </p>
- *
+ *
* @return the current system security policy.
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this method.
- * @since Android 1.0
*/
public static Policy getPolicy() {
SecurityManager sm = System.getSecurityManager();
@@ -170,7 +152,7 @@
// In case of any error, including undefined provider name,
// returns new instance of org.apache.harmony.security.FilePolicy provider.
private static Policy getDefaultProvider() {
- final String defaultClass = (String) AccessController
+ final String defaultClass = AccessController
.doPrivileged(new PolicyUtils.SecurityPropertyAccessor(
POLICY_PROVIDER));
if (defaultClass == null) {
@@ -235,14 +217,12 @@
* If a {@code SecurityManager} is installed, code calling this method needs
* the {@code SecurityPermission} {@code setPolicy} to be granted, otherwise
* a {@code SecurityException} will be thrown.
- * </p>
- *
+ *
* @param policy
* the {@code Policy} to set.
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this method.
- * @since Android 1.0
*/
public static void setPolicy(Policy policy) {
SecurityManager sm = System.getSecurityManager();
diff --git a/libcore/security/src/main/java/java/security/Principal.java b/libcore/security/src/main/java/java/security/Principal.java
index 0716681..f86bc87 100644
--- a/libcore/security/src/main/java/java/security/Principal.java
+++ b/libcore/security/src/main/java/java/security/Principal.java
@@ -15,40 +15,31 @@
* limitations under the License.
*/
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision$
-*/
-
package java.security;
/**
* {@code Principal}s are objects which have identities. These can be
* individuals, groups, corporations, unique program executions, etc.
- *
- * @since Android 1.0
*/
public interface Principal {
/**
* Compares the specified object with this {@code Principal} for equality
* and returns {@code true} if the specified object is equal, {@code false}
* otherwise.
- *
+ *
* @param obj
* object to be compared for equality with this {@code
* Principal}.
* @return {@code true} if the specified object is equal to this {@code
* Principal}, otherwise {@code false}.
- * @since Android 1.0
*/
public boolean equals( Object obj );
/**
* Returns the name of this {@code Principal}.
- *
+ *
* @return the name of this {@code Principal}.
- * @since Android 1.0
*/
public String getName();
@@ -60,16 +51,14 @@
* @return the hash code value for this {@code Principal}.
* @see Object#equals(Object)
* @see Principal#equals(Object)
- * @since Android 1.0
*/
public int hashCode();
-
- /**
+
+ /**
* Returns a string containing a concise, human-readable description of
* this {@code Principal}.
*
* @return a printable representation for this {@code Principal}.
- * @since Android 1.0
*/
public String toString();
}
diff --git a/libcore/security/src/main/java/java/security/PrivateKey.java b/libcore/security/src/main/java/java/security/PrivateKey.java
index 8513b75..246f286 100644
--- a/libcore/security/src/main/java/java/security/PrivateKey.java
+++ b/libcore/security/src/main/java/java/security/PrivateKey.java
@@ -15,25 +15,17 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
package java.security;
/**
* {@code PrivateKey} is the common interface for private keys.
*
* @see PublicKey
- * @since Android 1.0
*/
public interface PrivateKey extends Key {
-
+
/**
* The {@code serialVersionUID} to be compatible with JDK1.1.
- *
- * @since Android 1.0
*/
public static final long serialVersionUID = 6034044314589513430L;
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/PrivilegedAction.java b/libcore/security/src/main/java/java/security/PrivilegedAction.java
index 5912cdc..1dbbe65 100644
--- a/libcore/security/src/main/java/java/security/PrivilegedAction.java
+++ b/libcore/security/src/main/java/java/security/PrivilegedAction.java
@@ -15,31 +15,23 @@
* limitations under the License.
*/
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision$
-*/
-
package java.security;
/**
* {@code PrivilegedAction} represents an action that can be executed privileged
* regarding access control. Instances of {@code PrivilegedAction} can be
* executed on {@code AccessController.doPrivileged()}.
- *
+ *
* @see AccessController
* @see AccessController#doPrivileged(PrivilegedAction)
* @see AccessController#doPrivileged(PrivilegedAction, AccessControlContext)
* @see PrivilegedExceptionAction
- * @since Android 1.0
*/
public interface PrivilegedAction<T> {
-
/**
* Returns the result of running the action.
- *
+ *
* @return the result of running the action.
- * @since Android 1.0
*/
public T run();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/PrivilegedActionException.java b/libcore/security/src/main/java/java/security/PrivilegedActionException.java
index eaca2b2..a1f5b15 100644
--- a/libcore/security/src/main/java/java/security/PrivilegedActionException.java
+++ b/libcore/security/src/main/java/java/security/PrivilegedActionException.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision$
-*/
-
package java.security;
/**
@@ -33,13 +28,11 @@
* {@code AccessController#doPrivileged(PrivilegedExceptionAction,
* AccessControlContext)} </br>
* </ul>
- * </p>
- *
+ *
* @see PrivilegedExceptionAction
* @see AccessController#doPrivileged(PrivilegedExceptionAction)
* @see AccessController#doPrivileged(PrivilegedExceptionAction,
* AccessControlContext)
- * @since Android 1.0
*/
public class PrivilegedActionException extends Exception {
@@ -50,10 +43,9 @@
/**
* Constructs a new instance of {@code PrivilegedActionException} with the
* cause.
- *
+ *
* @param ex
* the exception which is the cause for this exception.
- * @since Android 1.0
*/
public PrivilegedActionException(Exception ex) {
super(ex);
@@ -63,10 +55,9 @@
/**
* Returns the exception that was thrown by a
* {@code PrivilegedExceptionAction}.
- *
+ *
* @return the exception that was thrown by a
* {@code PrivilegedExceptionAction}.
- * @since Android 1.0
*/
public Exception getException() {
return exception; // return ( getCause() instanceof Exception ) ?
@@ -76,11 +67,11 @@
/**
* Returns the exception that was thrown by a
* {@code PrivilegedExceptionAction}.
- *
+ *
* @return the exception that was thrown by a
* {@code PrivilegedExceptionAction}.
- * @since Android 1.0
*/
+ @Override
public Throwable getCause() {
return exception;
}
@@ -88,11 +79,11 @@
/**
* Returns a string containing a concise, human-readable description of this
* {@code PrivilegedActionException}.
- *
+ *
* @return a printable representation for this {@code
* PrivilegedActionException}.
- * @since Android 1.0
*/
+ @Override
public String toString() {
String s = getClass().getName();
return exception == null ? s : s + ": " + exception; //$NON-NLS-1$
diff --git a/libcore/security/src/main/java/java/security/PrivilegedExceptionAction.java b/libcore/security/src/main/java/java/security/PrivilegedExceptionAction.java
index dd3ae8d..bc072d5 100644
--- a/libcore/security/src/main/java/java/security/PrivilegedExceptionAction.java
+++ b/libcore/security/src/main/java/java/security/PrivilegedExceptionAction.java
@@ -15,34 +15,26 @@
* limitations under the License.
*/
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision$
-*/
-
package java.security;
/**
* {@code PrivilegedAction} represents an action, that can be executed
* privileged regarding access control. Instances of {@code PrivilegedAction}
* can be executed invoking {@code AccessController.doPrivileged()}.
- *
+ *
* @see AccessController
* @see AccessController#doPrivileged(PrivilegedExceptionAction)
* @see AccessController#doPrivileged(PrivilegedExceptionAction,
* AccessControlContext)
* @see PrivilegedAction
- * @since Android 1.0
*/
public interface PrivilegedExceptionAction<T> {
-
/**
* Returns the result of running the action.
- *
+ *
* @return the result of running the action
* @throws Exception
* if an exception occurred.
- * @since Android 1.0
*/
T run() throws Exception;
}
diff --git a/libcore/security/src/main/java/java/security/ProtectionDomain.java b/libcore/security/src/main/java/java/security/ProtectionDomain.java
index d41f4a8..1e85c4a 100644
--- a/libcore/security/src/main/java/java/security/ProtectionDomain.java
+++ b/libcore/security/src/main/java/java/security/ProtectionDomain.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision$
-*/
-
package java.security;
/**
@@ -30,9 +25,6 @@
* <p>
* A class belongs to exactly one protection domain and the protection domain
* can not be changed during the lifetime of the class.
- * </p>
- *
- * @since Android 1.0
*/
public class ProtectionDomain {
@@ -60,17 +52,13 @@
* collection is made immutable by calling
* {@link PermissionCollection#setReadOnly()} and it is considered as
* granted statically to this {@code ProtectionDomain}.
- * </p>
* <p>
* The policy will not be consulted by access checks against this {@code
* ProtectionDomain}.
- * </p>
* <p>
- * If {@code permissions} is {@code null}, the method
- * {@link ProtectionDomain#implies(Permission)} always returns {@code false}
- * .
- * </p>
- *
+ * If {@code permissions} is {@code null}, the method {@link
+ * ProtectionDomain#implies(Permission)} always returns {@code false}.
+ *
* @param cs
* the code source associated with this domain, maybe {@code
* null}.
@@ -78,7 +66,6 @@
* the {@code PermissionCollection} containing all permissions to
* be statically granted to this {@code ProtectionDomain}, maybe
* {@code null}.
- * @since Android 1.0
*/
public ProtectionDomain(CodeSource cs, PermissionCollection permissions) {
this.codeSource = cs;
@@ -91,7 +78,6 @@
//dynamicPerms = false;
}
-
/**
* Constructs a new instance of {@code ProtectionDomain} with the specified
* code source, the permissions, the class loader and the principals.
@@ -102,12 +88,10 @@
* permissions} collection is made immutable by calling
* {@link PermissionCollection#setReadOnly()}. If access checks are
* performed, the policy and the provided permission collection are checked.
- * </p>
* <p>
* External modifications of the provided {@code principals} array has no
* impact on this {@code ProtectionDomain}.
- * </p>
- *
+ *
* @param cs
* the code source associated with this domain, maybe {@code
* null}.
@@ -118,9 +102,8 @@
* the class loader associated with this domain, maybe {@code
* null}.
* @param principals
- * the principals associated with this domain, maybe {@code null}
- * .
- * @since Android 1.0
+ * the principals associated with this domain, maybe {@code
+ * null}.
*/
public ProtectionDomain(CodeSource cs, PermissionCollection permissions,
ClassLoader cl, Principal[] principals) {
@@ -141,10 +124,9 @@
/**
* Returns the {@code ClassLoader} associated with this {@code
* ProtectionDomain}.
- *
+ *
* @return the {@code ClassLoader} associated with this {@code
* ProtectionDomain}, maybe {@code null}.
- * @since Android 1.0
*/
public final ClassLoader getClassLoader() {
return classLoader;
@@ -152,10 +134,9 @@
/**
* Returns the {@code CodeSource} of this {@code ProtectionDomain}.
- *
+ *
* @return the {@code CodeSource} of this {@code ProtectionDomain}, maybe
* {@code null}.
- * @since Android 1.0
*/
public final CodeSource getCodeSource() {
return codeSource;
@@ -164,10 +145,9 @@
/**
* Returns the static permissions that are granted to this {@code
* ProtectionDomain}.
- *
+ *
* @return the static permissions that are granted to this {@code
* ProtectionDomain}, maybe {@code null}.
- * @since Android 1.0
*/
public final PermissionCollection getPermissions() {
return permissions;
@@ -177,9 +157,8 @@
* Returns the principals associated with this {@code ProtectionDomain}.
* Modifications of the returned {@code Principal} array has no impact on
* this {@code ProtectionDomain}.
- *
+ *
* @return the principals associated with this {@code ProtectionDomain}.
- * @since Android 1.0
*/
public final Principal[] getPrincipals() {
if( principals == null ) {
@@ -199,19 +178,16 @@
* specified permission is only checked against the permission collection
* provided in the constructor. If {@code null} was provided, {@code false}
* is returned.
- * </p>
* <p>
* If this {@code ProtectionDomain} was constructed with
* {@link #ProtectionDomain(CodeSource, PermissionCollection, ClassLoader, Principal[])}
* , the specified permission is checked against the policy and the
* permission collection provided in the constructor.
- * </p>
- *
+ *
* @param permission
* the permission to check against the domain.
* @return {@code true} if the specified {@code permission} is implied by
* this {@code ProtectionDomain}, {@code false} otherwise.
- * @since Android 1.0
*/
public boolean implies(Permission permission) {
// First, test with the Policy, as the default Policy.implies()
@@ -232,13 +208,12 @@
/**
* Returns a string containing a concise, human-readable description of the
* this {@code ProtectionDomain}.
- *
+ *
* @return a printable representation for this {@code ProtectionDomain}.
- * @since Android 1.0
*/
+ @Override
public String toString() {
- //FIXME: 1.5 use StreamBuilder here
- StringBuffer buf = new StringBuffer(200);
+ StringBuilder buf = new StringBuilder(200);
buf.append("ProtectionDomain\n"); //$NON-NLS-1$
buf.append("CodeSource=").append( //$NON-NLS-1$
codeSource == null ? "<null>" : codeSource.toString()).append( //$NON-NLS-1$
diff --git a/libcore/security/src/main/java/java/security/Provider.java b/libcore/security/src/main/java/java/security/Provider.java
index 491470f..cf9c94d 100644
--- a/libcore/security/src/main/java/java/security/Provider.java
+++ b/libcore/security/src/main/java/java/security/Provider.java
@@ -15,15 +15,11 @@
* limitations under the License.
*/
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
package java.security;
import java.io.IOException;
import java.io.InputStream;
+import java.io.NotActiveException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -37,14 +33,13 @@
import java.util.Set;
import org.apache.harmony.luni.util.TwoKeyHashMap;
+import org.apache.harmony.security.Util;
import org.apache.harmony.security.fortress.Services;
import org.apache.harmony.security.internal.nls.Messages;
/**
* {@code Provider} is the abstract superclass for all security providers in the
* Java security infrastructure.
- *
- * @since Android 1.0
*/
public abstract class Provider extends Properties {
private static final long serialVersionUID = -4298000515446427739L;
@@ -99,14 +94,13 @@
/**
* Constructs a new instance of {@code Provider} with its name, version and
* description.
- *
+ *
* @param name
* the name of the provider.
* @param version
* the version of the provider.
* @param info
* a description of the provider.
- * @since Android 1.0
*/
protected Provider(String name, double version, String info) {
this.name = name;
@@ -118,9 +112,8 @@
/**
* Returns the name of this provider.
- *
+ *
* @return the name of this provider.
- * @since Android 1.0
*/
public String getName() {
return name;
@@ -128,9 +121,8 @@
/**
* Returns the version number for the services being provided.
- *
+ *
* @return the version number for the services being provided.
- * @since Android 1.0
*/
public double getVersion() {
return version;
@@ -138,9 +130,8 @@
/**
* Returns a description of the services being provided.
- *
+ *
* @return a description of the services being provided.
- * @since Android 1.0
*/
public String getInfo() {
return info;
@@ -151,12 +142,10 @@
* this {@code Provider} including its name and its version.
*
* @return a printable representation for this {@code Provider}.
- * @since Android 1.0
*/
+ @Override
public String toString() {
- // BEGIN android-changed
return name + " version " + version; //$NON-NLS-1$
- // END android-changed
}
/**
@@ -167,13 +156,12 @@
* the {@code SecurityPermission} {@code clearProviderProperties.NAME}
* (where NAME is the provider name) to be granted, otherwise a {@code
* SecurityException} will be thrown.
- * </p>
- *
+ *
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this method.
- * @since Android 1.0
*/
+ @Override
public synchronized void clear() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
@@ -203,6 +191,7 @@
servicesChanged();
}
+ @Override
public synchronized void load(InputStream inStream) throws IOException {
Properties tmp = new Properties();
tmp.load(inStream);
@@ -216,15 +205,14 @@
* the {@code SecurityPermission} {@code putProviderProperty.NAME} (where
* NAME is the provider name) to be granted, otherwise a {@code
* SecurityException} will be thrown.
- * </p>
- *
+ *
* @param t
* the mappings to copy to this provider.
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this method.
- * @since Android 1.0
*/
+ @Override
public synchronized void putAll(Map<?,?> t) {
// Implementation note:
@@ -265,14 +253,17 @@
}
}
+ @Override
public synchronized Set<Map.Entry<Object,Object>> entrySet() {
return Collections.unmodifiableSet(super.entrySet());
}
+ @Override
public Set<Object> keySet() {
return Collections.unmodifiableSet(super.keySet());
}
+ @Override
public Collection<Object> values() {
return Collections.unmodifiableCollection(super.values());
}
@@ -285,8 +276,7 @@
* the {@code SecurityPermission} {@code putProviderProperty.NAME} (where
* NAME is the provider name) to be granted, otherwise a {@code
* SecurityException} will be thrown.
- * </p>
- *
+ *
* @param key
* the name of the property.
* @param value
@@ -296,8 +286,8 @@
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this method.
- * @since Android 1.0
*/
+ @Override
public synchronized Object put(Object key, Object value) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
@@ -329,8 +319,7 @@
* the {@code SecurityPermission} {@code removeProviderProperty.NAME} (where
* NAME is the provider name) to be granted, otherwise a {@code
* SecurityException} will be thrown.
- * </p>
- *
+ *
* @param key
* the name of the property
* @return the value that was mapped to the specified {@code key} ,or
@@ -338,8 +327,8 @@
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have the permission to invoke this method.
- * @since Android 1.0
*/
+ @Override
public synchronized Object remove(Object key) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
@@ -365,9 +354,9 @@
}
/**
- * returns true if the provider implements the specified algorithm. Caller
+ * Returns true if this provider implements the given algorithm. Caller
* must specify the cryptographic service and specify constraints via the
- * attribute name the attribute value
+ * attribute name and value.
*
* @param serv
* Crypto service.
@@ -386,33 +375,32 @@
alg = getPropertyIgnoreCase("Alg.Alias." + servAlg); //$NON-NLS-1$
if (alg != null) {
servAlg = serv + "." + alg; //$NON-NLS-1$
- prop = getPropertyIgnoreCase(serv + "." + alg); //$NON-NLS-1$
+ prop = getPropertyIgnoreCase(servAlg);
}
}
if (prop != null) {
if (attribute == null) {
return true;
- } else {
- return checkAttribute(serv + "." + alg, attribute, val); //$NON-NLS-1$
}
+ return checkAttribute(servAlg, attribute, val);
}
return false;
}
- // returns true if the implementation meets the constraint expressed by the
- // specified attribute name/value pair.
+ // Returns true if this provider has the same value as is given for the
+ // given attribute
private boolean checkAttribute(String servAlg, String attribute, String val) {
String attributeValue = getPropertyIgnoreCase(servAlg + ' ' + attribute);
if (attributeValue != null) {
- if (attribute.equalsIgnoreCase("KeySize")) { //$NON-NLS-1$
+ if (Util.equalsIgnoreCase(attribute,"KeySize")) { //$NON-NLS-1$
// BEGIN android-changed
if (Integer.parseInt(attributeValue) >= Integer.parseInt(val)) {
return true;
}
// END android-changed
} else { // other attributes
- if (attributeValue.equalsIgnoreCase(val)) {
+ if (Util.equalsIgnoreCase(attributeValue, val)) {
return true;
}
}
@@ -469,14 +457,13 @@
* If two services match the requested type and algorithm, the one added
* with the {@link #putService(Service)} is returned (as opposed to the one
* added via {@link #put(Object, Object)}.
- *
+ *
* @param type
* the type of the service (for example {@code KeyPairGenerator})
* @param algorithm
* the algorithm name (case insensitive)
* @return the requested service, or {@code null} if no such implementation
* exists
- * @since Android 1.0
*/
public synchronized Provider.Service getService(String type,
String algorithm) {
@@ -485,11 +472,11 @@
}
if (type.equals(lastServiceName)
- && algorithm.equalsIgnoreCase(lastAlgorithm)) {
+ && Util.equalsIgnoreCase(algorithm, lastAlgorithm)) {
return returnedService;
}
- String alg = algorithm.toUpperCase();
+ String alg = Util.toUpperCase(algorithm);
Object o = null;
if (serviceTable != null) {
o = serviceTable.get(type, alg);
@@ -519,10 +506,9 @@
/**
* Returns an unmodifiable {@code Set} of all services registered by this
* provider.
- *
+ *
* @return an unmodifiable {@code Set} of all services registered by this
* provider
- * @since Android 1.0
*/
public synchronized Set<Provider.Service> getServices() {
updatePropertyServiceTable();
@@ -549,13 +535,12 @@
* the {@code SecurityPermission} {@code putProviderProperty.NAME} (where
* NAME is the provider name) to be granted, otherwise a {@code
* SecurityException} will be thrown.
- *
+ *
* @param s
* the {@code Service} to register
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this method
- * @since Android 1.0
*/
protected synchronized void putService(Provider.Service s) {
if (s == null) {
@@ -573,13 +558,13 @@
if (serviceTable == null) {
serviceTable = new TwoKeyHashMap<String, String, Service>(128);
}
- serviceTable.put(s.type, s.algorithm.toUpperCase(), s);
+ serviceTable.put(s.type, Util.toUpperCase(s.algorithm), s);
if (s.aliases != null) {
if (aliasTable == null) {
aliasTable = new TwoKeyHashMap<String, String, Service>(256);
}
for (Iterator<String> it = s.getAliases(); it.hasNext();) {
- aliasTable.put(s.type, (it.next()).toUpperCase(), s);
+ aliasTable.put(s.type, Util.toUpperCase(it.next()), s);
}
}
serviceInfoToProperties(s);
@@ -593,7 +578,7 @@
* the {@code SecurityPermission} {@code removeProviderProperty.NAME} (where
* NAME is the provider name) to be granted, otherwise a {@code
* SecurityException} will be thrown.
- *
+ *
* @param s
* the {@code Service} to remove
* @throws SecurityException
@@ -601,7 +586,6 @@
* not have permission to invoke this method
* @throws NullPointerException
* if {@code s} is {@code null}
- * @since Android 1.0
*/
protected synchronized void removeService(Provider.Service s) {
if (s == null) {
@@ -613,11 +597,11 @@
}
servicesChanged();
if (serviceTable != null) {
- serviceTable.remove(s.type, s.algorithm.toUpperCase());
+ serviceTable.remove(s.type, Util.toUpperCase(s.algorithm));
}
if (aliasTable != null && s.aliases != null) {
for (Iterator<String> it = s.getAliases(); it.hasNext();) {
- aliasTable.remove(s.type, (it.next()).toUpperCase());
+ aliasTable.remove(s.type, Util.toUpperCase(it.next()));
}
}
serviceInfoFromProperties(s);
@@ -678,14 +662,14 @@
String algorithm = null;
String attribute = null;
int i;
- if (k.startsWith("Alg.Alias.")) { // Alg.Alias.<crypto_service>.<aliasName>=<stanbdardName> //$NON-NLS-1$
+ if (k.startsWith("Alg.Alias.")) { // Alg.Alias.<crypto_service>.<aliasName>=<standardName> //$NON-NLS-1$
String aliasName;
String service_alias = k.substring(10);
- i = service_alias.indexOf("."); //$NON-NLS-1$
+ i = service_alias.indexOf('.');
serviceName = service_alias.substring(0, i);
aliasName = service_alias.substring(i + 1);
if (propertyAliasTable != null) {
- propertyAliasTable.remove(serviceName, aliasName.toUpperCase());
+ propertyAliasTable.remove(serviceName, Util.toUpperCase(aliasName));
}
if (propertyServiceTable != null) {
for (Iterator<Service> it = propertyServiceTable.values().iterator(); it
@@ -699,22 +683,22 @@
}
return;
}
- int j = k.indexOf("."); //$NON-NLS-1$
+ int j = k.indexOf('.');
if (j == -1) { // unknown format
return;
}
- i = k.indexOf(" "); //$NON-NLS-1$
+ i = k.indexOf(' ');
if (i == -1) { // <crypto_service>.<algorithm_or_type>=<className>
serviceName = k.substring(0, j);
algorithm = k.substring(j + 1);
if (propertyServiceTable != null) {
- Provider.Service ser = propertyServiceTable.remove(serviceName, algorithm.toUpperCase());
+ Provider.Service ser = propertyServiceTable.remove(serviceName, Util.toUpperCase(algorithm));
if (ser != null && propertyAliasTable != null
&& ser.aliases != null) {
for (Iterator<String> it = ser.aliases.iterator(); it.hasNext();) {
- propertyAliasTable.remove(serviceName, (it
- .next()).toUpperCase());
+ propertyAliasTable.remove(serviceName, Util.toUpperCase(it
+ .next()));
}
}
}
@@ -724,8 +708,7 @@
serviceName = k.substring(0, j);
algorithm = k.substring(j + 1, i);
if (propertyServiceTable != null) {
- Object o = propertyServiceTable.get(serviceName, algorithm
- .toUpperCase());
+ Object o = propertyServiceTable.get(serviceName, Util.toUpperCase(algorithm));
if (o != null) {
s = (Provider.Service) o;
s.attributes.remove(attribute);
@@ -759,14 +742,14 @@
continue;
}
int i;
- if (key.startsWith("Alg.Alias.")) { // Alg.Alias.<crypto_service>.<aliasName>=<stanbdardName> //$NON-NLS-1$
+ if (key.startsWith("Alg.Alias.")) { // Alg.Alias.<crypto_service>.<aliasName>=<standardName> //$NON-NLS-1$
String aliasName;
String service_alias = key.substring(10);
- i = service_alias.indexOf("."); //$NON-NLS-1$
+ i = service_alias.indexOf('.');
serviceName = service_alias.substring(0, i);
aliasName = service_alias.substring(i + 1);
algorithm = value;
- String algUp = algorithm.toUpperCase();
+ String algUp = Util.toUpperCase(algorithm);
Object o = null;
if (propertyServiceTable == null) {
propertyServiceTable = new TwoKeyHashMap<String, String, Service>(128);
@@ -782,7 +765,7 @@
propertyAliasTable = new TwoKeyHashMap<String, String, Service>(256);
}
propertyAliasTable.put(serviceName,
- aliasName.toUpperCase(), s);
+ Util.toUpperCase(aliasName), s);
} else {
String className = (String) changedProperties
.get(serviceName + "." + algorithm); //$NON-NLS-1$
@@ -795,21 +778,21 @@
if (propertyAliasTable == null) {
propertyAliasTable = new TwoKeyHashMap<String, String, Service>(256);
}
- propertyAliasTable.put(serviceName, aliasName
- .toUpperCase(), s);
+ propertyAliasTable.put(serviceName, Util.toUpperCase(aliasName
+ ), s);
}
}
continue;
}
- int j = key.indexOf("."); //$NON-NLS-1$
+ int j = key.indexOf('.');
if (j == -1) { // unknown format
continue;
}
- i = key.indexOf(" "); //$NON-NLS-1$
+ i = key.indexOf(' ');
if (i == -1) { // <crypto_service>.<algorithm_or_type>=<className>
serviceName = key.substring(0, j);
algorithm = key.substring(j + 1);
- String alg = algorithm.toUpperCase();
+ String alg = Util.toUpperCase(algorithm);
Object o = null;
if (propertyServiceTable != null) {
o = propertyServiceTable.get(serviceName, alg);
@@ -834,7 +817,7 @@
serviceName = key.substring(0, j);
algorithm = key.substring(j + 1, i);
String attribute = key.substring(i + 1);
- String alg = algorithm.toUpperCase();
+ String alg = Util.toUpperCase(algorithm);
Object o = null;
if (propertyServiceTable != null) {
o = propertyServiceTable.get(serviceName, alg);
@@ -875,11 +858,12 @@
// These attributes should be placed in each Provider object:
// Provider.id name, Provider.id version, Provider.id info,
// Provider.id className
+ @SuppressWarnings("nls")
private void putProviderInfo() {
- super.put("Provider.id name", null != name ? name : "null"); //$NON-NLS-1$
- super.put("Provider.id version", versionString); //$NON-NLS-1$
- super.put("Provider.id info", null != info ? info : "null"); //$NON-NLS-1$
- super.put("Provider.id className", this.getClass().getName()); //$NON-NLS-1$
+ super.put("Provider.id name", null != name ? name : "null");
+ super.put("Provider.id version", versionString);
+ super.put("Provider.id info", null != info ? info : "null");
+ super.put("Provider.id className", this.getClass().getName());
}
// Searches for the property with the specified key in the provider
@@ -894,7 +878,7 @@
}
for (Enumeration<?> e = propertyNames(); e.hasMoreElements();) {
String pname = (String) e.nextElement();
- if (key.equalsIgnoreCase(pname)) {
+ if (Util.equalsIgnoreCase(key, pname)) {
return getProperty(pname);
}
}
@@ -905,8 +889,6 @@
* {@code Service} represents a service in the Java Security infrastructure.
* Each service describes its type, the algorithm it implements, to which
* provider it belongs and other properties.
- *
- * @since Android 1.0
*/
public static class Service {
// The provider
@@ -936,7 +918,7 @@
/**
* Constructs a new instance of {@code Service} with the given
* attributes.
- *
+ *
* @param provider
* the provider to which this service belongs.
* @param type
@@ -955,7 +937,6 @@
* @throws NullPointerException
* if {@code provider, type, algorithm} or {@code className}
* is {@code null}.
- * @since Android 1.0
*/
public Service(Provider provider, String type, String algorithm,
String className, List<String> aliases, Map<String, String> attributes) {
@@ -1006,21 +987,19 @@
/**
* Returns the type of this {@code Service}. For example {@code
* KeyPairGenerator}.
- *
+ *
* @return the type of this {@code Service}.
- * @since Android 1.0
*/
public final String getType() {
return type;
}
/**
- * Returns the name of the algorithm implemented by this {@code Service}
- * .
- *
- * @return the name of the algorithm implemented by this {@code Service}
- * .
- * @since Android 1.0
+ * Returns the name of the algorithm implemented by this {@code
+ * Service}.
+ *
+ * @return the name of the algorithm implemented by this {@code
+ * Service}.
*/
public final String getAlgorithm() {
return algorithm;
@@ -1028,9 +1007,8 @@
/**
* Returns the {@code Provider} this {@code Service} belongs to.
- *
+ *
* @return the {@code Provider} this {@code Service} belongs to.
- * @since Android 1.0
*/
public final Provider getProvider() {
return provider;
@@ -1038,9 +1016,8 @@
/**
* Returns the name of the class implementing this {@code Service}.
- *
+ *
* @return the name of the class implementing this {@code Service}.
- * @since Android 1.0
*/
public final String getClassName() {
return className;
@@ -1048,14 +1025,13 @@
/**
* Returns the value of the attribute with the specified {@code name}.
- *
+ *
* @param name
* the name of the attribute.
* @return the value of the attribute, or {@code null} if no attribute
* with the given name is set.
* @throws NullPointerException
* if {@code name} is {@code null}.
- * @since Android 1.0
*/
public final String getAttribute(String name) {
if (name == null) {
@@ -1068,13 +1044,16 @@
}
Iterator<String> getAliases() {
+ if(aliases == null){
+ aliases = new ArrayList<String>(0);
+ }
return aliases.iterator();
}
/**
* Creates and returns a new instance of the implementation described by
* this {@code Service}.
- *
+ *
* @param constructorParameter
* the parameter that is used by the constructor, or {@code
* null} if the implementation does not declare a constructor
@@ -1086,7 +1065,6 @@
* @throws InvalidParameterException
* if the implementation does not support the specified
* {@code constructorParameter}.
- * @since Android 1.0
*/
public Object newInstance(Object constructorParameter)
throws NoSuchAlgorithmException {
@@ -1122,39 +1100,37 @@
throw new NoSuchAlgorithmException(Messages.getString("security.199", //$NON-NLS-1$
type, algorithm), e);
}
- } else {
- if (!supportsParameter(constructorParameter)) {
- throw new InvalidParameterException(
- Messages.getString("security.12", type)); //$NON-NLS-1$
- }
+ }
+ if (!supportsParameter(constructorParameter)) {
+ throw new InvalidParameterException(
+ Messages.getString("security.12", type)); //$NON-NLS-1$
+ }
- Class[] parameterTypes = new Class[1];
- Object[] initargs = { constructorParameter };
- try {
- if (type.equalsIgnoreCase("CertStore")) { //$NON-NLS-1$
- parameterTypes[0] = Class
- .forName("java.security.cert.CertStoreParameters"); //$NON-NLS-1$
- } else {
- parameterTypes[0] = constructorParameter.getClass();
- }
- return implementation.getConstructor(parameterTypes)
- .newInstance(initargs);
- } catch (Exception e) {
- throw new NoSuchAlgorithmException(Messages.getString("security.199", //$NON-NLS-1$
- type, algorithm), e);
+ Class[] parameterTypes = new Class[1];
+ Object[] initargs = { constructorParameter };
+ try {
+ if (Util.equalsIgnoreCase(type,"CertStore")) { //$NON-NLS-1$
+ parameterTypes[0] = Class
+ .forName("java.security.cert.CertStoreParameters"); //$NON-NLS-1$
+ } else {
+ parameterTypes[0] = constructorParameter.getClass();
}
+ return implementation.getConstructor(parameterTypes)
+ .newInstance(initargs);
+ } catch (Exception e) {
+ throw new NoSuchAlgorithmException(Messages.getString("security.199", //$NON-NLS-1$
+ type, algorithm), e);
}
}
/**
* Indicates whether this {@code Service} supports the specified
* constructor parameter.
- *
+ *
* @param parameter
* the parameter to test.
* @return {@code true} if this {@code Service} supports the specified
* constructor parameter, {@code false} otherwise.
- * @since Android 1.0
*/
public boolean supportsParameter(Object parameter) {
return true;
@@ -1163,10 +1139,10 @@
/**
* Returns a string containing a concise, human-readable description of
* this {@code Service}.
- *
+ *
* @return a printable representation for this {@code Service}.
- * @since Android 1.0
*/
+ @Override
public String toString() {
String result = "Provider " + provider.getName() + " Service " //$NON-NLS-1$ //$NON-NLS-2$
+ type + "." + algorithm + " " + className; //$NON-NLS-1$ //$NON-NLS-2$
@@ -1179,4 +1155,10 @@
return result;
}
}
+
+ private void readObject(java.io.ObjectInputStream in) throws NotActiveException, IOException, ClassNotFoundException {
+ in.defaultReadObject();
+ versionString = String.valueOf(version);
+ providerNumber = -1;
+ }
}
diff --git a/libcore/security/src/main/java/java/security/ProviderException.java b/libcore/security/src/main/java/java/security/ProviderException.java
index d4def5b..22950f5 100644
--- a/libcore/security/src/main/java/java/security/ProviderException.java
+++ b/libcore/security/src/main/java/java/security/ProviderException.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
package java.security;
/**
@@ -27,7 +22,6 @@
* Providers}.
*
* @see Provider
- * @since Android 1.0
*/
public class ProviderException extends RuntimeException {
@@ -36,10 +30,9 @@
/**
* Constructs a new instance of {@code ProviderException} with the given
* message.
- *
+ *
* @param msg
* the detail message for this exception.
- * @since Android 1.0
*/
public ProviderException(String msg) {
super(msg);
@@ -47,8 +40,6 @@
/**
* Constructs a new instance of {@code ProviderException}.
- *
- * @since Android 1.0
*/
public ProviderException() {
}
@@ -56,12 +47,11 @@
/**
* Constructs a new instance of {@code ProviderException} with the given
* message and the cause.
- *
+ *
* @param message
* the detail message for this exception.
* @param cause
* the exception which is the cause for this exception.
- * @since Android 1.0
*/
public ProviderException(String message, Throwable cause) {
super(message, cause);
@@ -69,12 +59,11 @@
/**
* Constructs a new instance of {@code ProviderException} with the cause.
- *
+ *
* @param cause
* the exception which is the cause for this exception.
- * @since Android 1.0
*/
public ProviderException(Throwable cause) {
super(cause);
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/PublicKey.java b/libcore/security/src/main/java/java/security/PublicKey.java
index 4888a64..c197840 100644
--- a/libcore/security/src/main/java/java/security/PublicKey.java
+++ b/libcore/security/src/main/java/java/security/PublicKey.java
@@ -15,25 +15,16 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
package java.security;
/**
* {@code PublicKey} is the common interface for public keys.
*
* @see PrivateKey
- * @since Android 1.0
*/
public interface PublicKey extends Key {
-
/**
* The {@code serialVersionUID} to be compatible with JDK1.1.
- *
- * @since Android 1.0
*/
public static final long serialVersionUID = 7187392471159151072L;
}
diff --git a/libcore/security/src/main/java/java/security/SecureClassLoader.java b/libcore/security/src/main/java/java/security/SecureClassLoader.java
index 7d08fc8..07bebc9 100644
--- a/libcore/security/src/main/java/java/security/SecureClassLoader.java
+++ b/libcore/security/src/main/java/java/security/SecureClassLoader.java
@@ -15,28 +15,20 @@
* limitations under the License.
*/
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision$
-*/
-
package java.security;
import java.nio.ByteBuffer;
import java.util.HashMap;
-
/**
* {@code SecureClassLoader} represents a {@code ClassLoader} which associates
* the classes it loads with a code source and provide mechanisms to allow the
* relevant permissions to be retrieved.
- *
- * @since Android 1.0
*/
public class SecureClassLoader extends ClassLoader {
// A cache of ProtectionDomains for a given CodeSource
- private HashMap pds = new HashMap();
+ private HashMap<CodeSource, ProtectionDomain> pds = new HashMap<CodeSource, ProtectionDomain>();
/**
* Constructs a new instance of {@code SecureClassLoader}. The default
@@ -45,12 +37,10 @@
* If a {@code SecurityManager} is installed, code calling this constructor
* needs the {@code SecurityPermission} {@code checkCreateClassLoader} to be
* granted, otherwise a {@code SecurityException} will be thrown.
- * </p>
- *
+ *
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this constructor.
- * @since Android 1.0
*/
protected SecureClassLoader() {
super();
@@ -63,14 +53,12 @@
* If a {@code SecurityManager} is installed, code calling this constructor
* needs the {@code SecurityPermission} {@code checkCreateClassLoader} to be
* granted, otherwise a {@code SecurityException} will be thrown.
- * </p>
- *
+ *
* @param parent
* the parent {@code ClassLoader}.
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this constructor.
- * @since Android 1.0
*/
protected SecureClassLoader(ClassLoader parent) {
super(parent);
@@ -79,12 +67,11 @@
/**
* Returns the {@code PermissionCollection} for the specified {@code
* CodeSource}.
- *
+ *
* @param codesource
* the code source.
* @return the {@code PermissionCollection} for the specified {@code
* CodeSource}.
- * @since Android 1.0
*/
protected PermissionCollection getPermissions(CodeSource codesource) {
// Do nothing by default, ProtectionDomain will take care about
@@ -95,7 +82,7 @@
/**
* Constructs a new class from an array of bytes containing a class
* definition in class file format with an optional {@code CodeSource}.
- *
+ *
* @param name
* the name of the new class.
* @param b
@@ -116,7 +103,6 @@
* if the package to which this class is to be added, already
* contains classes which were signed by different certificates,
* or if the class name begins with "java."
- * @since Android 1.0
*/
protected final Class<?> defineClass(String name, byte[] b, int off, int len,
CodeSource cs) {
@@ -127,7 +113,7 @@
/**
* Constructs a new class from an array of bytes containing a class
* definition in class file format with an optional {@code CodeSource}.
- *
+ *
* @param name
* the name of the new class.
* @param b
@@ -141,7 +127,6 @@
* if the package to which this class is to be added, already
* contains classes which were signed by different certificates,
* or if the class name begins with "java."
- * @since Android 1.0
*/
protected final Class<?> defineClass(String name, ByteBuffer b, CodeSource cs) {
//FIXME 1.5 - remove b.array(), call super.defineClass(,ByteBuffer,)
@@ -165,7 +150,7 @@
// will have it's own ProtectionDomain, which does not look right.
ProtectionDomain pd;
synchronized (pds) {
- if ((pd = (ProtectionDomain) pds.get(cs)) != null) {
+ if ((pd = pds.get(cs)) != null) {
return pd;
}
PermissionCollection perms = getPermissions(cs);
diff --git a/libcore/security/src/main/java/java/security/SecureRandom.java b/libcore/security/src/main/java/java/security/SecureRandom.java
index e1d99e9..c697504 100644
--- a/libcore/security/src/main/java/java/security/SecureRandom.java
+++ b/libcore/security/src/main/java/java/security/SecureRandom.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
package java.security;
import java.util.Iterator;
@@ -35,8 +30,6 @@
/**
* {@code SecureRandom} is an engine class which is capable of generating
* cryptographically secure pseudo-random numbers.
- *
- * @since Android 1.0
*/
public class SecureRandom extends Random {
@@ -50,7 +43,7 @@
private Provider provider;
- private SecureRandomSpi secureRandomSpi;
+ private SecureRandomSpi secureRandomSpi;
private String algorithm;
@@ -69,8 +62,6 @@
* Constructs a new instance of {@code SecureRandom}. An implementation for
* the highest-priority provider is returned. The constructed instance will
* not have been seeded.
- *
- * @since Android 1.0
*/
public SecureRandom() {
super(0);
@@ -97,7 +88,6 @@
*
* @param seed
* the seed for this generator.
- * @since Android 1.0
*/
public SecureRandom(byte[] seed) {
this();
@@ -125,7 +115,6 @@
* the implementation.
* @param provider
* the security provider.
- * @since Android 1.0
*/
protected SecureRandom(SecureRandomSpi secureRandomSpi,
Provider provider) {
@@ -154,7 +143,6 @@
* if the specified algorithm is not available.
* @throws NullPointerException
* if {@code algorithm} is {@code null}.
- * @since Android 1.0
*/
public static SecureRandom getInstance(String algorithm)
throws NoSuchAlgorithmException {
@@ -183,7 +171,6 @@
* if the specified provider is not available.
* @throws NullPointerException
* if {@code algorithm} is {@code null}.
- * @since Android 1.0
*/
public static SecureRandom getInstance(String algorithm, String provider)
throws NoSuchAlgorithmException, NoSuchProviderException {
@@ -212,7 +199,6 @@
* if the specified algorithm is not available.
* @throws NullPointerException
* if {@code algorithm} is {@code null}.
- * @since Android 1.0
*/
public static SecureRandom getInstance(String algorithm, Provider provider)
throws NoSuchAlgorithmException {
@@ -232,7 +218,6 @@
* Returns the provider associated with this {@code SecureRandom}.
*
* @return the provider associated with this {@code SecureRandom}.
- * @since Android 1.0
*/
public final Provider getProvider() {
return provider;
@@ -242,7 +227,6 @@
* Returns the name of the algorithm of this {@code SecureRandom}.
*
* @return the name of the algorithm of this {@code SecureRandom}.
- * @since Android 1.0
*/
public String getAlgorithm() {
return algorithm;
@@ -255,7 +239,6 @@
*
* @param seed
* the new seed.
- * @since Android 1.0
*/
public synchronized void setSeed(byte[] seed) {
secureRandomSpi.engineSetSeed(seed);
@@ -268,8 +251,8 @@
*
* @param seed
* the new seed.
- * @since Android 1.0
*/
+ @Override
public void setSeed(long seed) {
if (seed == 0) { // skip call from Random
return;
@@ -293,8 +276,8 @@
*
* @param bytes
* the {@code byte[]} to be filled with random bytes.
- * @since Android 1.0
*/
+ @Override
public synchronized void nextBytes(byte[] bytes) {
secureRandomSpi.engineNextBytes(bytes);
}
@@ -307,8 +290,8 @@
* number of bits to be generated. An input value should be in
* the range [0, 32].
* @return an {@code int} containing the specified number of random bits.
- * @since Android 1.0
*/
+ @Override
protected final int next(int numBits) {
if (numBits < 0) {
numBits = 0;
@@ -336,7 +319,6 @@
* @param numBytes
* the number of seed bytes.
* @return the seed bytes
- * @since Android 1.0
*/
public static byte[] getSeed(int numBytes) {
if (internalSecureRandom == null) {
@@ -352,7 +334,6 @@
* @param numBytes
* the number of seed bytes.
* @return the seed bytes.
- * @since Android 1.0
*/
public byte[] generateSeed(int numBytes) {
return secureRandomSpi.engineGenerateSeed(numBytes);
diff --git a/libcore/security/src/main/java/java/security/SecureRandomSpi.java b/libcore/security/src/main/java/java/security/SecureRandomSpi.java
index 7ce880c..829464f 100644
--- a/libcore/security/src/main/java/java/security/SecureRandomSpi.java
+++ b/libcore/security/src/main/java/java/security/SecureRandomSpi.java
@@ -15,21 +15,15 @@
* limitations under the License.
*/
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
package java.security;
import java.io.Serializable;
/**
* {@code SecureRandomSpi} is the <i>Service Provider Interface</i> (<b>SPI</b>) definition
- * for {@link SecureRandom}.
+ * for {@link SecureRandom}.
*
* @see SecureRandom
- * @since Android 1.0
*/
public abstract class SecureRandomSpi implements Serializable {
@@ -42,7 +36,6 @@
*
* @param seed
* the new seed.
- * @since Android 1.0
*/
protected abstract void engineSetSeed(byte[] seed);
@@ -52,7 +45,6 @@
*
* @param bytes
* the {@code byte[]} to be filled with random bytes.
- * @since Android 1.0
*/
protected abstract void engineNextBytes(byte[] bytes);
@@ -63,7 +55,6 @@
* @param numBytes
* the number of seed bytes.
* @return the seed bytes
- * @since Android 1.0
*/
protected abstract byte[] engineGenerateSeed(int numBytes);
}
diff --git a/libcore/security/src/main/java/java/security/Security.java b/libcore/security/src/main/java/java/security/Security.java
index 505a557..6ff38ad 100644
--- a/libcore/security/src/main/java/java/security/Security.java
+++ b/libcore/security/src/main/java/java/security/Security.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
package java.security;
import java.io.BufferedInputStream;
@@ -39,7 +34,9 @@
import java.util.Map;
import java.util.Properties;
import java.util.Set;
+import java.util.Map.Entry;
+import org.apache.harmony.security.Util;
import org.apache.harmony.security.fortress.Engine;
import org.apache.harmony.security.fortress.PolicyUtils;
import org.apache.harmony.security.fortress.SecurityAccess;
@@ -50,8 +47,6 @@
* {@code Security} is the central class in the Java Security API. It manages
* the list of security {@code Provider} that have been installed into this
* runtime environment.
- *
- * @since Android 1.0
*/
public final class Security {
@@ -87,57 +82,40 @@
// END android-added
// BEGIN android-removed
- // File f = new File(System.getProperty("java.home") //$NON-NLS-1$
- // + File.separator + "lib" + File.separator //$NON-NLS-1$
- // + "security" + File.separator + "java.security"); //$NON-NLS-1$ //$NON-NLS-2$
- // if (f.exists()) {
- // try {
- // FileInputStream fis = new FileInputStream(f);
- // InputStream is = new BufferedInputStream(fis);
- // secprops.load(is);
- // loaded = true;
- // is.close();
- // } catch (IOException e) {
- //// System.err.println("Could not load Security properties file: "
- //// + e);
- // }
- // }
- //
- // if ("true".equalsIgnoreCase(secprops.getProperty("security.allowCustomPropertiesFile", "true"))) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- // String securityFile = System.getProperty("java.security.properties"); //$NON-NLS-1$
- // if (securityFile != null) {
- // if (securityFile.startsWith("=")) { // overwrite //$NON-NLS-1$
- // secprops = new Properties();
- // loaded = false;
- // securityFile = securityFile.substring(1);
- // }
- // try {
- // securityFile = PolicyUtils.expand(securityFile, System.getProperties());
- // } catch (PolicyUtils.ExpansionFailedException e) {
- //// System.err.println("Could not load custom Security properties file "
- //// + securityFile +": " + e);
- // }
- // f = new File(securityFile);
- // InputStream is;
- // try {
- // if (f.exists()) {
- // FileInputStream fis = new FileInputStream(f);
- // is = new BufferedInputStream(fis);
- // } else {
- // URL url = new URL(securityFile);
- // is = new BufferedInputStream(url.openStream());
- // }
- // secprops.load(is);
- // loaded = true;
- // is.close();
- // } catch (IOException e) {
- // // System.err.println("Could not load custom Security properties file "
- // // + securityFile +": " + e);
- // }
- // }
- // }
+// if (Util.equalsIgnoreCase("true", secprops.getProperty("security.allowCustomPropertiesFile", "true"))) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+// String securityFile = System.getProperty("java.security.properties"); //$NON-NLS-1$
+// if (securityFile != null) {
+// if (securityFile.startsWith("=")) { // overwrite //$NON-NLS-1$
+// secprops = new Properties();
+// loaded = false;
+// securityFile = securityFile.substring(1);
+// }
+// try {
+// securityFile = PolicyUtils.expand(securityFile, System.getProperties());
+// } catch (PolicyUtils.ExpansionFailedException e) {
+//// System.err.println("Could not load custom Security properties file "
+//// + securityFile +": " + e);
+// }
+// f = new File(securityFile);
+// InputStream is;
+// try {
+// if (f.exists()) {
+// FileInputStream fis = new FileInputStream(f);
+// is = new BufferedInputStream(fis);
+// } else {
+// URL url = new URL(securityFile);
+// is = new BufferedInputStream(url.openStream());
+// }
+// secprops.load(is);
+// loaded = true;
+// is.close();
+// } catch (IOException e) {
+// // System.err.println("Could not load custom Security properties file "
+// // + securityFile +": " + e);
+// }
+// }
+// }
// END android-removed
-
if (!loaded) {
registerDefaultProviders();
}
@@ -161,12 +139,9 @@
secprops.put("security.provider.4", "org.bouncycastle.jce.provider.BouncyCastleProvider"); //$NON-NLS-1$ //$NON-NLS-2$
}
- // BEGIN android-note
- // added Deprecated annotation
- // END android-note
/**
* Returns value for the specified algorithm with the specified name.
- *
+ *
* @param algName
* the name of the algorithm.
* @param propName
@@ -174,7 +149,6 @@
* @return value of the property.
* @deprecated Use {@link AlgorithmParameters} and {@link KeyFactory}
* instead.
- * @since Android 1.0
*/
@Deprecated
public static String getAlgorithmProperty(String algName, String propName) {
@@ -189,7 +163,7 @@
for (Enumeration e = providers[i].propertyNames(); e
.hasMoreElements();) {
String pname = (String) e.nextElement();
- if (prop.equalsIgnoreCase(pname)) {
+ if (Util.equalsIgnoreCase(prop, pname)) {
return providers[i].getProperty(pname);
}
}
@@ -206,8 +180,7 @@
* the {@code SecurityPermission} {@code insertProvider.NAME} (where NAME is
* the provider name) to be granted, otherwise a {@code SecurityException}
* will be thrown.
- * </p>
- *
+ *
* @param provider
* the provider to insert.
* @param position
@@ -218,7 +191,6 @@
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this method.
- * @since Android 1.0
*/
public static synchronized int insertProviderAt(Provider provider,
int position) {
@@ -246,8 +218,7 @@
* the {@code SecurityPermission} {@code insertProvider.NAME} (where NAME is
* the provider name) to be granted, otherwise a {@code SecurityException}
* will be thrown.
- * </p>
- *
+ *
* @param provider
* the provider to be added.
* @return the actual position or {@code -1} if the given {@code provider}
@@ -255,7 +226,6 @@
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this method.
- * @since Android 1.0
*/
public static int addProvider(Provider provider) {
return insertProviderAt(provider, 0);
@@ -269,20 +239,17 @@
* <p>
* Returns silently if {@code name} is {@code null} or no provider with the
* specified name is installed.
- * </p>
* <p>
* If a {@code SecurityManager} is installed, code calling this method needs
* the {@code SecurityPermission} {@code removeProvider.NAME} (where NAME is
* the provider name) to be granted, otherwise a {@code SecurityException}
* will be thrown.
- * </p>
- *
+ *
* @param name
* the name of the provider to remove.
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this method.
- * @since Android 1.0
*/
public static synchronized void removeProvider(String name) {
// It is not clear from spec.:
@@ -311,9 +278,8 @@
/**
* Returns an array containing all installed providers. The providers are
* ordered according their preference order.
- *
+ *
* @return an array containing all installed providers.
- * @since Android 1.0
*/
public static synchronized Provider[] getProviders() {
return Services.getProviders();
@@ -323,11 +289,10 @@
* Returns the {@code Provider} with the specified name. Returns {@code
* null} if name is {@code null} or no provider with the specified name is
* installed.
- *
+ *
* @param name
* the name of the requested provider.
* @return the provider with the specified name, maybe {@code null}.
- * @since Android 1.0
*/
public static synchronized Provider getProvider(String name) {
return Services.getProvider(name);
@@ -337,15 +302,15 @@
* Returns the array of providers which meet the user supplied string
* filter. The specified filter must be supplied in one of two formats:
* <nl>
- * <li> CRYPTO_SERVICE_NAME.ALGORITHM_OR_TYPE
+ * <li> CRYPTO_SERVICE_NAME.ALGORITHM_OR_TYPE
* <p>
- * (for example: "MessageDigest.SHA")
+ * (for example: "MessageDigest.SHA")
* <li> CRYPTO_SERVICE_NAME.ALGORITHM_OR_TYPE
* ATTR_NAME:ATTR_VALUE
* <p>
- * (for example: "Signature.MD5withRSA KeySize:512")
+ * (for example: "Signature.MD2withRSA KeySize:512")
* </nl>
- *
+ *
* @param filter
* case-insensitive filter.
* @return the providers which meet the user supplied string filter {@code
@@ -355,7 +320,6 @@
* if an unusable filter is supplied.
* @throws NullPointerException
* if {@code filter} is {@code null}.
- * @since Android 1.0
*/
public static Provider[] getProviders(String filter) {
if (filter == null) {
@@ -366,7 +330,7 @@
Messages.getString("security.2B")); //$NON-NLS-1$
}
HashMap<String, String> hm = new HashMap<String, String>();
- int i = filter.indexOf(":"); //$NON-NLS-1$
+ int i = filter.indexOf(':');
if ((i == filter.length() - 1) || (i == 0)) {
throw new InvalidParameterException(
Messages.getString("security.2B")); //$NON-NLS-1$
@@ -389,10 +353,10 @@
* be an empty string. <li> CRYPTO_SERVICE_NAME.ALGORITHM_OR_TYPE
* ATTR_NAME:ATTR_VALUE
* <p>
- * for example: "Signature.MD5withRSA KeySize:512" where "KeySize:512" is
+ * for example: "Signature.MD2withRSA KeySize:512" where "KeySize:512" is
* the value of the filter map entry.
* </nl>
- *
+ *
* @param filter
* case-insensitive filter.
* @return the providers which meet the user supplied string filter {@code
@@ -402,7 +366,6 @@
* if an unusable filter is supplied.
* @throws NullPointerException
* if {@code filter} is {@code null}.
- * @since Android 1.0
*/
public static synchronized Provider[] getProviders(Map<String,String> filter) {
if (filter == null) {
@@ -412,15 +375,15 @@
return null;
}
java.util.List<Provider> result = Services.getProvidersList();
- Set keys = filter.entrySet();
- Map.Entry entry;
- for (Iterator it = keys.iterator(); it.hasNext();) {
- entry = (Map.Entry) it.next();
- String key = (String) entry.getKey();
- String val = (String) entry.getValue();
+ Set<Entry<String, String>> keys = filter.entrySet();
+ Map.Entry<String, String> entry;
+ for (Iterator<Entry<String, String>> it = keys.iterator(); it.hasNext();) {
+ entry = it.next();
+ String key = entry.getKey();
+ String val = entry.getValue();
String attribute = null;
- int i = key.indexOf(" "); //$NON-NLS-1$
- int j = key.indexOf("."); //$NON-NLS-1$
+ int i = key.indexOf(' ');
+ int j = key.indexOf('.');
if (j == -1) {
throw new InvalidParameterException(
Messages.getString("security.2B")); //$NON-NLS-1$
@@ -451,7 +414,7 @@
Provider p;
for (int k = 0; k < result.size(); k++) {
try {
- p = (Provider) result.get(k);
+ p = result.get(k);
} catch (IndexOutOfBoundsException e) {
break;
}
@@ -463,9 +426,8 @@
}
if (result.size() > 0) {
return result.toArray(new Provider[result.size()]);
- } else {
- return null;
}
+ return null;
}
/**
@@ -475,15 +437,13 @@
* the {@code SecurityPermission} {@code getProperty.KEY} (where KEY is the
* specified {@code key}) to be granted, otherwise a {@code
* SecurityException} will be thrown.
- * </p>
- *
+ *
* @param key
* the name of the requested security property.
* @return the value of the security property.
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this method.
- * @since Android 1.0
*/
public static String getProperty(String key) {
if (key == null) {
@@ -493,7 +453,11 @@
if (sm != null) {
sm.checkSecurityAccess("getProperty." + key); //$NON-NLS-1$
}
- return secprops.getProperty(key);
+ String property = secprops.getProperty(key);
+ if (property != null) {
+ property = property.trim();
+ }
+ return property;
}
/**
@@ -503,8 +467,7 @@
* the {@code SecurityPermission} {@code setProperty.KEY} (where KEY is the
* specified {@code key}) to be granted, otherwise a {@code
* SecurityException} will be thrown.
- * </p>
- *
+ *
* @param key
* the name of the security property.
* @param datnum
@@ -512,7 +475,6 @@
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this method.
- * @since Android 1.0
*/
public static void setProperty(String key, String datnum) {
SecurityManager sm = System.getSecurityManager();
@@ -526,22 +488,27 @@
* Returns a {@code Set} of all registered algorithms for the specified
* cryptographic service. {@code "Signature"}, {@code "Cipher"} and {@code
* "KeyStore"} are examples for such kind of services.
- *
+ *
* @param serviceName
* the case-insensitive name of the service.
* @return a {@code Set} of all registered algorithms for the specified
* cryptographic service, or an empty {@code Set} if {@code
* serviceName} is {@code null} or if no registered provider
* provides the requested service.
- * @since Android 1.0
*/
public static Set<String> getAlgorithms(String serviceName) {
Set<String> result = new HashSet<String>();
+ // BEGIN android-added
+ // compatibility with RI
+ if (serviceName == null) {
+ return result;
+ }
+ // END android-added
Provider[] p = getProviders();
for (int i = 0; i < p.length; i++) {
for (Iterator it = p[i].getServices().iterator(); it.hasNext();) {
Provider.Service s = (Provider.Service) it.next();
- if (s.getType().equalsIgnoreCase(serviceName)) {
+ if (Util.equalsIgnoreCase(s.getType(),serviceName)) {
result.add(s.getAlgorithm());
}
}
diff --git a/libcore/security/src/main/java/java/security/SecurityPermission.java b/libcore/security/src/main/java/java/security/SecurityPermission.java
index 87f3aaa..599ec6f 100644
--- a/libcore/security/src/main/java/java/security/SecurityPermission.java
+++ b/libcore/security/src/main/java/java/security/SecurityPermission.java
@@ -15,18 +15,11 @@
* limitations under the License.
*/
-/**
-* @author Alexey V. Varlamov
-* @version $Revision$
-*/
-
package java.security;
/**
* {@code SecurityPermission} objects guard access to the mechanisms which
* implement security. Security permissions have names, but not actions.
- *
- * @since Android 1.0
*/
public final class SecurityPermission extends BasicPermission {
@@ -35,10 +28,9 @@
/**
* Constructs a new instance of {@code SecurityPermission} with the given
* name.
- *
+ *
* @param name
* the name of the permission.
- * @since Android 1.0
*/
public SecurityPermission(String name) {
super(name);
@@ -48,12 +40,11 @@
* Constructs a new instance of {@code SecurityPermission} with the given
* {@code name} and {@code action} list. The action list is ignored - it is
* existing for compatibility reasons only.
- *
+ *
* @param name
* the name of the permission.
* @param action
* ignored.
- * @since Android 1.0
*/
public SecurityPermission(String name, String action) {
super(name, action);
diff --git a/libcore/security/src/main/java/java/security/Signature.java b/libcore/security/src/main/java/java/security/Signature.java
index e5d488e..4e3fe14 100644
--- a/libcore/security/src/main/java/java/security/Signature.java
+++ b/libcore/security/src/main/java/java/security/Signature.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
package java.security;
import java.nio.ByteBuffer;
@@ -39,7 +34,6 @@
* registered with the {@link Security} class.
*
* @see SignatureSpi
- * @since Android 1.0
*/
public abstract class Signature extends SignatureSpi {
@@ -58,24 +52,18 @@
/**
* Constant that indicates that this {@code Signature} instance has not yet
* been initialized.
- *
- * @since Android 1.0
*/
protected static final int UNINITIALIZED = 0;
/**
* Constant that indicates that this {@code Signature} instance has been
* initialized for signing.
- *
- * @since Android 1.0
*/
protected static final int SIGN = 2;
/**
* Constant that indicates that this {@code Signature} instance has been
* initialized for verification.
- *
- * @since Android 1.0
*/
protected static final int VERIFY = 3;
@@ -83,18 +71,15 @@
* Represents the current state of this {@code Signature}. The three
* possible states are {@link #UNINITIALIZED}, {@link #SIGN} or
* {@link #VERIFY}.
- *
- * @since Android 1.0
*/
protected int state = UNINITIALIZED;
/**
* Constructs a new instance of {@code Signature} with the name of
* the algorithm to use.
- *
+ *
* @param algorithm
* the name of algorithm to use.
- * @since Android 1.0
*/
protected Signature(String algorithm) {
this.algorithm = algorithm;
@@ -103,7 +88,7 @@
/**
* Returns a new instance of {@code Signature} that utilizes the specified
* algorithm.
- *
+ *
* @param algorithm
* the name of the algorithm to use.
* @return a new instance of {@code Signature} that utilizes the specified
@@ -112,7 +97,6 @@
* if the specified algorithm is not available.
* @throws NullPointerException
* if {@code algorithm} is {@code null}.
- * @since Android 1.0
*/
public static Signature getInstance(String algorithm)
throws NoSuchAlgorithmException {
@@ -137,7 +121,7 @@
/**
* Returns a new instance of {@code Signature} that utilizes the specified
* algorithm from the specified provider.
- *
+ *
* @param algorithm
* the name of the algorithm to use.
* @param provider
@@ -150,7 +134,6 @@
* if the specified provider is not available.
* @throws NullPointerException
* if {@code algorithm} is {@code null}.
- * @since Android 1.0
*/
public static Signature getInstance(String algorithm, String provider)
throws NoSuchAlgorithmException, NoSuchProviderException {
@@ -171,7 +154,7 @@
/**
* Returns a new instance of {@code Signature} that utilizes the specified
* algorithm from the specified provider.
- *
+ *
* @param algorithm
* the name of the algorithm to use.
* @param provider
@@ -182,7 +165,6 @@
* if the specified algorithm is not available.
* @throws NullPointerException
* if {@code algorithm} is {@code null}.
- * @since Android 1.0
*/
public static Signature getInstance(String algorithm, Provider provider)
throws NoSuchAlgorithmException {
@@ -214,9 +196,8 @@
/**
* Returns the provider associated with this {@code Signature}.
- *
+ *
* @return the provider associated with this {@code Signature}.
- * @since Android 1.0
*/
public final Provider getProvider() {
return provider;
@@ -224,9 +205,8 @@
/**
* Returns the name of the algorithm of this {@code Signature}.
- *
+ *
* @return the name of the algorithm of this {@code Signature}.
- * @since Android 1.0
*/
public final String getAlgorithm() {
return algorithm;
@@ -236,12 +216,11 @@
* Initializes this {@code Signature} instance for signature verification,
* using the public key of the identity whose signature is going to be
* verified.
- *
+ *
* @param publicKey
* the public key.
* @throws InvalidKeyException
* if {@code publicKey} is not valid.
- * @since Android 1.0
*/
public final void initVerify(PublicKey publicKey)
throws InvalidKeyException {
@@ -257,14 +236,12 @@
* If the given certificate is an instance of {@link X509Certificate} and
* has a key usage parameter that indicates, that this certificate is not to
* be used for signing, an {@code InvalidKeyException} is thrown.
- * </p>
- *
+ *
* @param certificate
* the certificate used to verify a signature.
* @throws InvalidKeyException
* if the publicKey in the certificate is not valid or not to be
* used for signing.
- * @since Android 1.0
*/
public final void initVerify(Certificate certificate)
throws InvalidKeyException {
@@ -302,12 +279,11 @@
/**
* Initializes this {@code Signature} instance for signing, using the
* private key of the identity whose signature is going to be generated.
- *
+ *
* @param privateKey
* the private key.
* @throws InvalidKeyException
* if {@code privateKey} is not valid.
- * @since Android 1.0
*/
public final void initSign(PrivateKey privateKey)
throws InvalidKeyException {
@@ -319,14 +295,13 @@
* Initializes this {@code Signature} instance for signing, using the
* private key of the identity whose signature is going to be generated and
* the specified source of randomness.
- *
+ *
* @param privateKey
* the private key.
* @param random
* the {@code SecureRandom} to use.
* @throws InvalidKeyException
* if {@code privateKey} is not valid.
- * @since Android 1.0
*/
public final void initSign(PrivateKey privateKey, SecureRandom random)
throws InvalidKeyException {
@@ -340,13 +315,11 @@
* This {@code Signature} instance is reset to the state of its last
* initialization for signing and thus can be used for another signature
* from the same identity.
- * </p>
- *
+ *
* @return the signature of all updated data.
* @throws SignatureException
* if this {@code Signature} instance is not initialized
* properly.
- * @since Android 1.0
*/
public final byte[] sign() throws SignatureException {
if (state != SIGN) {
@@ -363,8 +336,7 @@
* This {@code Signature} instance is reset to the state of its last
* initialization for signing and thus can be used for another signature
* from the same identity.
- * </p>
- *
+ *
* @param outbuf
* the buffer to store the signature.
* @param offset
@@ -378,7 +350,6 @@
* @throws IllegalArgumentException
* if {@code offset} or {@code len} are not valid in respect to
* {@code outbuf}.
- * @since Android 1.0
*/
public final int sign(byte[] outbuf, int offset, int len)
throws SignatureException {
@@ -401,8 +372,7 @@
* This {@code Signature} instance is reset to the state of its last
* initialization for verifying and thus can be used to verify another
* signature of the same signer.
- * </p>
- *
+ *
* @param signature
* the signature to verify.
* @return {@code true} if the signature was verified, {@code false}
@@ -410,7 +380,6 @@
* @throws SignatureException
* if this {@code Signature} instance is not initialized
* properly.
- * @since Android 1.0
*/
public final boolean verify(byte[] signature) throws SignatureException {
if (state != VERIFY) {
@@ -428,8 +397,7 @@
* This {@code Signature} instance is reset to the state of its last
* initialization for verifying and thus can be used to verify another
* signature of the same signer.
- * </p>
- *
+ *
* @param signature
* the {@code byte[]} containing the signature to verify.
* @param offset
@@ -444,7 +412,6 @@
* @throws IllegalArgumentException
* if {@code offset} or {@code length} are not valid in respect
* to {@code signature}.
- * @since Android 1.0
*/
public final boolean verify(byte[] signature, int offset, int length)
throws SignatureException {
@@ -463,13 +430,12 @@
/**
* Updates the data to be verified or to be signed, using the specified
* {@code byte}.
- *
+ *
* @param b
* the byte to update with.
* @throws SignatureException
* if this {@code Signature} instance is not initialized
* properly.
- * @since Android 1.0
*/
public final void update(byte b) throws SignatureException {
if (state == UNINITIALIZED) {
@@ -482,13 +448,12 @@
/**
* Updates the data to be verified or to be signed, using the specified
* {@code byte[]}.
- *
+ *
* @param data
* the byte array to update with.
* @throws SignatureException
* if this {@code Signature} instance is not initialized
* properly.
- * @since Android 1.0
*/
public final void update(byte[] data) throws SignatureException {
if (state == UNINITIALIZED) {
@@ -501,7 +466,7 @@
/**
* Updates the data to be verified or to be signed, using the given {@code
* byte[]}, starting form the specified index for the specified length.
- *
+ *
* @param data
* the byte array to update with.
* @param off
@@ -511,7 +476,6 @@
* @throws SignatureException
* if this {@code Signature} instance is not initialized
* properly.
- * @since Android 1.0
*/
public final void update(byte[] data, int off, int len)
throws SignatureException {
@@ -530,13 +494,12 @@
/**
* Updates the data to be verified or to be signed, using the specified
* {@code ByteBuffer}.
- *
+ *
* @param data
* the {@code ByteBuffer} to update with.
* @throws SignatureException
* if this {@code Signature} instance is not initialized
* properly.
- * @since Android 1.0
*/
public final void update(ByteBuffer data) throws SignatureException {
if (state == UNINITIALIZED) {
@@ -549,10 +512,10 @@
/**
* Returns a string containing a concise, human-readable description of this
* {@code Signature} including its algorithm and its state.
- *
+ *
* @return a printable representation for this {@code Signature}.
- * @since Android 1.0
*/
+ @Override
public String toString() {
return "SIGNATURE " + algorithm + " state: " + stateToString(state); //$NON-NLS-1$ //$NON-NLS-2$
}
@@ -571,12 +534,9 @@
}
}
- // BEGIN android-note
- // added Deprecated annotation
- // END android-note
/**
* Sets the specified parameter to the given value.
- *
+ *
* @param param
* the name of the parameter.
* @param value
@@ -585,7 +545,6 @@
* if the parameter is invalid, already set or is not allowed to
* be changed.
* @deprecated Use {@link #setParameter(AlgorithmParameterSpec)}
- * @since Android 1.0
*/
@Deprecated
public final void setParameter(String param, Object value)
@@ -595,13 +554,12 @@
/**
* Sets the specified {@code AlgorithmParameterSpec}.
- *
+ *
* @param params
* the parameter to set.
* @throws InvalidAlgorithmParameterException
* if the parameter is invalid, already set or is not allowed to
* be changed.
- * @since Android 1.0
*/
public final void setParameter(AlgorithmParameterSpec params)
throws InvalidAlgorithmParameterException {
@@ -611,18 +569,14 @@
/**
* Returns the {@code AlgorithmParameters} of this {@link Signature}
* instance.
- *
+ *
* @return the {@code AlgorithmParameters} of this {@link Signature}
* instance, maybe {@code null}.
- * @since Android 1.0
*/
public final AlgorithmParameters getParameters() {
return engineGetParameters();
}
- // BEGIN android-note
- // added Deprecated annotation
- // END android-note
/**
* Returns the value of the parameter with the specified name.
*
@@ -634,7 +588,6 @@
* if {@code param} is not a valid parameter for this {@code
* Signature} or an other error occures.
* @deprecated There is no generally accepted parameter naming convention.
- * @since Android 1.0
*/
@Deprecated
public final Object getParameter(String param)
@@ -642,12 +595,12 @@
return engineGetParameter(param);
}
+ @Override
public Object clone() throws CloneNotSupportedException {
if (this instanceof Cloneable) {
return super.clone();
- } else {
- throw new CloneNotSupportedException();
}
+ throw new CloneNotSupportedException();
}
/**
@@ -668,58 +621,66 @@
}
// engineSign() implementation
+ @Override
protected byte[] engineSign() throws SignatureException {
return spiImpl.engineSign();
}
// engineUpdate() implementation
+ @Override
protected void engineUpdate(byte arg0) throws SignatureException {
spiImpl.engineUpdate(arg0);
}
// engineVerify() implementation
+ @Override
protected boolean engineVerify(byte[] arg0) throws SignatureException {
return spiImpl.engineVerify(arg0);
}
// engineUpdate() implementation
+ @Override
protected void engineUpdate(byte[] arg0, int arg1, int arg2)
throws SignatureException {
spiImpl.engineUpdate(arg0, arg1, arg2);
}
// engineInitSign() implementation
+ @Override
protected void engineInitSign(PrivateKey arg0)
throws InvalidKeyException {
spiImpl.engineInitSign(arg0);
}
// engineInitVerify() implementation
+ @Override
protected void engineInitVerify(PublicKey arg0)
throws InvalidKeyException {
spiImpl.engineInitVerify(arg0);
}
// engineGetParameter() implementation
+ @Override
protected Object engineGetParameter(String arg0)
throws InvalidParameterException {
return spiImpl.engineGetParameter(arg0);
}
// engineSetParameter() implementation
+ @Override
protected void engineSetParameter(String arg0, Object arg1)
throws InvalidParameterException {
spiImpl.engineSetParameter(arg0, arg1);
}
// Returns a clone if the spiImpl is cloneable
+ @Override
public Object clone() throws CloneNotSupportedException {
if (spiImpl instanceof Cloneable) {
SignatureSpi spi = (SignatureSpi) spiImpl.clone();
return new SignatureImpl(spi, getProvider(), getAlgorithm());
- } else {
- throw new CloneNotSupportedException();
}
+ throw new CloneNotSupportedException();
}
}
}
diff --git a/libcore/security/src/main/java/java/security/SignatureException.java b/libcore/security/src/main/java/java/security/SignatureException.java
index f07c34b..f8909d1 100644
--- a/libcore/security/src/main/java/java/security/SignatureException.java
+++ b/libcore/security/src/main/java/java/security/SignatureException.java
@@ -15,18 +15,12 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
package java.security;
/**
*{@code SignatureException} is a general {@code Signature} exception.
*
* @see Signature
- * @since Android 1.0
*/
public class SignatureException extends GeneralSecurityException {
@@ -35,10 +29,9 @@
/**
* Constructs a new instance of {@code SignatureException} with the
* given message.
- *
+ *
* @param msg
* the detail message for this exception.
- * @since Android 1.0
*/
public SignatureException(String msg) {
super(msg);
@@ -46,8 +39,6 @@
/**
* Constructs a new instance of {@code SignatureException}.
- *
- * @since Android 1.0
*/
public SignatureException() {
}
@@ -55,12 +46,11 @@
/**
* Constructs a new instance of {@code SignatureException} with the
* given message and the cause.
- *
+ *
* @param message
* the detail message for this exception
* @param cause
* the exception which is the cause for this exception
- * @since Android 1.0
*/
public SignatureException(String message, Throwable cause) {
super(message, cause);
@@ -69,10 +59,9 @@
/**
* Constructs a new instance of {@code SignatureException} with the
* cause.
- *
+ *
* @param cause
* the exception which is the cause for this exception
- * @since Android 1.0
*/
public SignatureException(Throwable cause) {
super(cause);
diff --git a/libcore/security/src/main/java/java/security/SignatureSpi.java b/libcore/security/src/main/java/java/security/SignatureSpi.java
index 738d489..93c9e8c 100644
--- a/libcore/security/src/main/java/java/security/SignatureSpi.java
+++ b/libcore/security/src/main/java/java/security/SignatureSpi.java
@@ -14,10 +14,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
package java.security;
@@ -31,14 +27,11 @@
* definition for {@link Signature}.
*
* @see Signature
- * @since Android 1.0
*/
public abstract class SignatureSpi {
/**
* Implementation specific source of randomness.
- *
- * @since Android 1.0
*/
protected SecureRandom appRandom;
@@ -46,12 +39,11 @@
* Initializes this {@code SignatureSpi} instance for signature
* verification, using the public key of the identity whose signature is
* going to be verified.
- *
+ *
* @param publicKey
* the public key.
* @throws InvalidKeyException
* if {@code publicKey} is not valid.
- * @since Android 1.0
*/
protected abstract void engineInitVerify(PublicKey publicKey)
throws InvalidKeyException;
@@ -59,12 +51,11 @@
/**
* Initializes this {@code SignatureSpi} instance for signing, using the
* private key of the identity whose signature is going to be generated.
- *
+ *
* @param privateKey
* the private key.
* @throws InvalidKeyException
* if {@code privateKey} is not valid.
- * @since Android 1.0
*/
protected abstract void engineInitSign(PrivateKey privateKey)
throws InvalidKeyException;
@@ -73,14 +64,13 @@
* Initializes this {@code SignatureSpi} instance for signing, using the
* private key of the identity whose signature is going to be generated and
* the specified source of randomness.
- *
+ *
* @param privateKey
* the private key.
* @param random
* the {@code SecureRandom} to use.
* @throws InvalidKeyException
* if {@code privateKey} is not valid.
- * @since Android 1.0
*/
protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
throws InvalidKeyException {
@@ -91,20 +81,19 @@
/**
* Updates the data to be verified or to be signed, using the specified
* {@code byte}.
- *
+ *
* @param b
* the byte to update with.
* @throws SignatureException
* if this {@code SignatureSpi} instance is not initialized
* properly.
- * @since Android 1.0
*/
protected abstract void engineUpdate(byte b) throws SignatureException;
/**
* Updates the data to be verified or to be signed, using the given {@code
* byte[]}, starting form the specified index for the specified length.
- *
+ *
* @param b
* the byte array to update with.
* @param off
@@ -114,7 +103,6 @@
* @throws SignatureException
* if this {@code SignatureSpi} instance is not initialized
* properly.
- * @since Android 1.0
*/
protected abstract void engineUpdate(byte[] b, int off, int len)
throws SignatureException;
@@ -130,7 +118,6 @@
* method it throws a {@code RuntimeException} if underlying
* {@link #engineUpdate(byte[], int, int)} throws {@code
* SignatureException}.
- * @since Android 1.0
*/
protected void engineUpdate(ByteBuffer input) {
if (!input.hasRemaining()) {
@@ -165,13 +152,11 @@
* This {@code SignatureSpi} instance is reset to the state of its last
* initialization for signing and thus can be used for another signature
* from the same identity.
- * </p>
- *
+ *
* @return the signature of all updated data.
* @throws SignatureException
* if this {@code SignatureSpi} instance is not initialized
* properly.
- * @since Android 1.0
*/
protected abstract byte[] engineSign() throws SignatureException;
@@ -182,8 +167,7 @@
* This {@code SignatureSpi} instance is reset to the state of its last
* initialization for signing and thus can be used for another signature
* from the same identity.
- * </p>
- *
+ *
* @param outbuf
* the buffer to store the signature.
* @param offset
@@ -197,7 +181,6 @@
* @throws IllegalArgumentException
* if {@code offset} or {@code len} are not valid in respect to
* {@code outbuf}.
- * @since Android 1.0
*/
protected int engineSign(byte[] outbuf, int offset, int len)
throws SignatureException {
@@ -225,8 +208,7 @@
* This {@code SignatureSpi} instance is reset to the state of its last
* initialization for verifying and thus can be used to verify another
* signature of the same signer.
- * </p>
- *
+ *
* @param sigBytes
* the signature to verify.
* @return {@code true} if the signature was verified, {@code false}
@@ -234,7 +216,6 @@
* @throws SignatureException
* if this {@code SignatureSpi} instance is not initialized
* properly.
- * @since Android 1.0
*/
protected abstract boolean engineVerify(byte[] sigBytes)
throws SignatureException;
@@ -247,8 +228,7 @@
* This {@code SignatureSpi} instance is reset to the state of its last
* initialization for verifying and thus can be used to verify another
* signature of the same signer.
- * </p>
- *
+ *
* @param sigBytes
* the {@code byte[]} containing the signature to verify.
* @param offset
@@ -263,7 +243,6 @@
* @throws IllegalArgumentException
* if {@code offset} or {@code length} are not valid in respect
* to {@code sigBytes}.
- * @since Android 1.0
*/
protected boolean engineVerify(byte[] sigBytes, int offset, int length)
throws SignatureException {
@@ -274,7 +253,7 @@
/**
* Sets the specified parameter to the given value.
- *
+ *
* @param param
* the name of the parameter.
* @param value
@@ -283,7 +262,6 @@
* if the parameter is invalid, already set or is not allowed to
* be changed.
* @deprecated Use {@link #engineSetParameter(AlgorithmParameterSpec)}
- * @since Android 1.0
*/
@Deprecated
protected abstract void engineSetParameter(String param, Object value)
@@ -291,13 +269,12 @@
/**
* Sets the specified {@code AlgorithmParameterSpec}.
- *
+ *
* @param params
* the parameter to set.
* @throws InvalidAlgorithmParameterException
* if the parameter is invalid, already set or is not allowed to
* be changed.
- * @since Android 1.0
*/
protected void engineSetParameter(AlgorithmParameterSpec params)
throws InvalidAlgorithmParameterException {
@@ -307,21 +284,17 @@
/**
* Returns the {@code AlgorithmParameters} of this {@link SignatureSpi}
* instance.
- *
+ *
* @return the {@code AlgorithmParameters} of this {@link SignatureSpi}
* instance, maybe {@code null}.
- * @since Android 1.0
*/
protected AlgorithmParameters engineGetParameters() {
throw new UnsupportedOperationException();
}
- // BEGIN android-note
- // added Deprecated annotation
- // END android-note
/**
* Returns the value of the parameter with the specified name.
- *
+ *
* @param param
* the name of the requested parameter value.
* @return the value of the parameter with the specified name, maybe {@code
@@ -330,17 +303,16 @@
* if {@code param} is not a valid parameter for this {@code
* SignatureSpi} or an other error occurs.
* @deprecated There is no generally accepted parameter naming convention.
- * @since Android 1.0
*/
@Deprecated
protected abstract Object engineGetParameter(String param)
throws InvalidParameterException;
+ @Override
public Object clone() throws CloneNotSupportedException {
if (this instanceof Cloneable) {
return super.clone();
- } else {
- throw new CloneNotSupportedException();
}
+ throw new CloneNotSupportedException();
}
}
diff --git a/libcore/security/src/main/java/java/security/SignedObject.java b/libcore/security/src/main/java/java/security/SignedObject.java
index d2022c8..3347cf3 100644
--- a/libcore/security/src/main/java/java/security/SignedObject.java
+++ b/libcore/security/src/main/java/java/security/SignedObject.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
package java.security;
import java.io.ByteArrayInputStream;
@@ -33,8 +28,6 @@
* A {@code SignedObject} instance acts as a container for another object. The
* {@code SignedObject} contains the target in serialized form along with a
* digital signature of the serialized data.
- *
- * @since Android 1.0
*/
public final class SignedObject implements Serializable {
@@ -75,7 +68,6 @@
* if the private key is not valid.
* @throws SignatureException
* if signature generation failed.
- * @since Android 1.0
*/
public SignedObject(Serializable object, PrivateKey signingKey,
Signature signingEngine) throws IOException, InvalidKeyException,
@@ -106,7 +98,6 @@
* if deserialization failed.
* @throws ClassNotFoundException
* if the class of the encapsulated object can not be found.
- * @since Android 1.0
*/
public Object getObject() throws IOException, ClassNotFoundException {
// deserialize our object
@@ -123,7 +114,6 @@
* Returns the signature data of the encapsulated serialized object.
*
* @return the signature data of the encapsulated serialized object.
- * @since Android 1.0
*/
public byte[] getSignature() {
byte[] sig = new byte[signature.length];
@@ -135,7 +125,6 @@
* Returns the name of the algorithm of this {@code SignedObject}.
*
* @return the name of the algorithm of this {@code SignedObject}.
- * @since Android 1.0
*/
public String getAlgorithm() {
return thealgorithm;
@@ -155,7 +144,6 @@
* if the public key is invalid.
* @throws SignatureException
* if signature verification failed.
- * @since Android 1.0
*/
public boolean verify(PublicKey verificationKey,
Signature verificationEngine) throws InvalidKeyException,
@@ -166,4 +154,4 @@
return verificationEngine.verify(signature);
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/Signer.java b/libcore/security/src/main/java/java/security/Signer.java
index 9e48226..64996bf 100644
--- a/libcore/security/src/main/java/java/security/Signer.java
+++ b/libcore/security/src/main/java/java/security/Signer.java
@@ -15,16 +15,8 @@
* limitations under the License.
*/
-/**
- * @author Aleksei Y. Semenov
- * @version $Revision$
- */
-
package java.security;
-// BEGIN android-note
-// added Deprecated annotation
-// END android-note
/**
* {@link Signer} represents an identity (individual or corporation) that owns a
* private key and the corresponding public key.
@@ -32,7 +24,6 @@
* @deprecated Replaced by behavior in {@link java.security.cert
* java.security.cert} package and {@link java.security.Principal
* Principal}
- * @since Android 1.0
*/
@Deprecated
public abstract class Signer extends Identity {
@@ -43,8 +34,6 @@
/**
* Constructs a new instance of {@code Signer}.
- *
- * @since Android 1.0
*/
protected Signer() {
super();
@@ -52,10 +41,9 @@
/**
* Constructs a new instance of {@code Signer} with the given name.
- *
+ *
* @param name
* the name of the signer.
- * @since Android 1.0
*/
public Signer(String name) {
super(name);
@@ -64,7 +52,7 @@
/**
* Constructs a new instance of {@code Signer} with the given name in the
* given scope.
- *
+ *
* @param name
* the name of the signer.
* @param scope
@@ -72,7 +60,6 @@
* @throws KeyManagementException
* if a signer with the specified name already exists in the
* provided scope.
- * @since Android 1.0
*/
public Signer(String name, IdentityScope scope)
throws KeyManagementException {
@@ -84,12 +71,11 @@
* SecurityManager} is installed, code calling this method needs the {@code
* SecurityPermission} {@code "getSignerPrivateKey"} to be granted, otherwise
* a {@code SecurityException} will be thrown.
- *
+ *
* @return the private key of this {@code Signer}.
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this method.
- * @since Android 1.0
*/
public PrivateKey getPrivateKey() {
SecurityManager sm = System.getSecurityManager();
@@ -105,7 +91,7 @@
* SecurityManager} is installed, code calling this method needs the {@code
* SecurityPermission} {@code getSignerPrivateKey} to be granted, otherwise
* a {@code SecurityException} will be thrown.
- *
+ *
* @param pair
* the key pair to associate with this {@code Signer}.
* @throws InvalidParameterException
@@ -115,7 +101,6 @@
* @throws SecurityException
* if a {@code SecurityManager} is installed and the caller does
* not have permission to invoke this method.
- * @since Android 1.0
*/
public final void setKeyPair(KeyPair pair)
throws InvalidParameterException, KeyException {
@@ -148,10 +133,10 @@
/**
* Returns a string containing a concise, human-readable description of this
* {@code Signer} including its name and its scope if present.
- *
+ *
* @return a printable representation for this {@code Signer}.
- * @since Android 1.0
*/
+ @Override
public String toString() {
String s = "[Signer]" + getName(); //$NON-NLS-1$
if (getScope() != null) {
diff --git a/libcore/security/src/main/java/java/security/Timestamp.java b/libcore/security/src/main/java/java/security/Timestamp.java
index 1d31e6f..5a2930a 100644
--- a/libcore/security/src/main/java/java/security/Timestamp.java
+++ b/libcore/security/src/main/java/java/security/Timestamp.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision$
-*/
-
package java.security;
import java.io.Serializable;
@@ -31,8 +26,6 @@
/**
* {@code Timestamp} represents a signed time stamp. {@code Timestamp} is
* immutable.
- *
- * @since Android 1.0
*/
public final class Timestamp implements Serializable {
@@ -48,7 +41,7 @@
/**
* Constructs a new instance of {@code Timestamp} with the specified {@code
* timestamp} and the given certificate path.
- *
+ *
* @param timestamp
* date and time.
* @param signerCertPath
@@ -56,7 +49,6 @@
* @throws NullPointerException
* if {@code timestamp} is {@code null} or if {@code
* signerCertPath} is {@code null}.
- * @since Android 1.0
*/
public Timestamp(Date timestamp, CertPath signerCertPath) {
if (timestamp == null) {
@@ -76,15 +68,15 @@
* otherwise. The given object is equal to this {@code Timestamp}, if it is
* an instance of {@code Timestamp}, the two timestamps have an equal date
* and time and their certificate paths are equal.
- *
+ *
* @param obj
* object to be compared for equality with this {@code
* Timestamp}.
* @return {@code true} if the specified object is equal to this {@code
* Timestamp}, otherwise {@code false}.
* @see #hashCode
- * @since Android 1.0
*/
+ @Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
@@ -99,9 +91,8 @@
/**
* Returns the certificate path of this {@code Timestamp}.
- *
+ *
* @return the certificate path of this {@code Timestamp}.
- * @since Android 1.0
*/
public CertPath getSignerCertPath() {
return signerCertPath;
@@ -109,15 +100,11 @@
/**
* Returns the date and time of this {@code Timestamp}.
- *
+ *
* @return the date and time of this {@code Timestamp}.
- * @since Android 1.0
*/
public Date getTimestamp() {
- // BEGIN android-changed
- // copied from a newer version of harmony
return (Date) timestamp.clone();
- // END android-changed
}
/**
@@ -128,8 +115,8 @@
* @return the hash code value for this {@code Timestamp}.
* @see Object#equals(Object)
* @see Timestamp#equals(Object)
- * @since Android 1.0
*/
+ @Override
public int hashCode() {
if (hash == 0) {
hash = timestamp.hashCode() ^ signerCertPath.hashCode();
@@ -140,15 +127,15 @@
/**
* Returns a string containing a concise, human-readable description of this
* {@code Timestamp}.
- *
+ *
* @return a printable representation for this {@code Timestamp}.
- * @since Android 1.0
*/
+ @Override
public String toString() {
- StringBuffer buf = new StringBuffer(256);
+ StringBuilder buf = new StringBuilder(256);
// Dump only the first certificate
buf.append("Timestamp [").append(timestamp).append(" certPath="); //$NON-NLS-1$ //$NON-NLS-2$
buf.append(signerCertPath.getCertificates().get(0)).append("]"); //$NON-NLS-1$
return buf.toString();
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/UnrecoverableEntryException.java b/libcore/security/src/main/java/java/security/UnrecoverableEntryException.java
index dc2981a..24ff54b 100644
--- a/libcore/security/src/main/java/java/security/UnrecoverableEntryException.java
+++ b/libcore/security/src/main/java/java/security/UnrecoverableEntryException.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
package java.security;
@@ -29,7 +24,6 @@
*
* @see KeyStore
* @see KeyStore.Entry
- * @since Android 1.0
*/
public class UnrecoverableEntryException extends GeneralSecurityException {
@@ -37,8 +31,6 @@
/**
* Constructs a new instance of {@code UnrecoverableEntryException}.
- *
- * @since Android 1.0
*/
public UnrecoverableEntryException() {
}
@@ -46,12 +38,11 @@
/**
* Constructs a new instance of {@code UnrecoverableEntryException} with the
* given message.
- *
+ *
* @param msg
* the detail message for this exception.
- * @since Android 1.0
*/
public UnrecoverableEntryException(String msg) {
super(msg);
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/UnrecoverableKeyException.java b/libcore/security/src/main/java/java/security/UnrecoverableKeyException.java
index e4b399b..3840e6b 100644
--- a/libcore/security/src/main/java/java/security/UnrecoverableKeyException.java
+++ b/libcore/security/src/main/java/java/security/UnrecoverableKeyException.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
package java.security;
/**
@@ -27,7 +22,6 @@
* from a {@code KeyStore}.
*
* @see KeyStore
- * @since Android 1.0
*/
public class UnrecoverableKeyException extends GeneralSecurityException {
@@ -36,10 +30,9 @@
/**
* Constructs a new instance of {@code UnrecoverableKeyException} with the
* given message.
- *
+ *
* @param msg
* the detail message for this exception
- * @since Android 1.0
*/
public UnrecoverableKeyException(String msg) {
super(msg);
@@ -47,8 +40,6 @@
/**
* Constructs a new instance of {@code UnrecoverableKeyException}.
- *
- * @since Android 1.0
*/
public UnrecoverableKeyException() {
}
diff --git a/libcore/security/src/main/java/java/security/UnresolvedPermission.java b/libcore/security/src/main/java/java/security/UnresolvedPermission.java
index 6570de4..bf99a40 100644
--- a/libcore/security/src/main/java/java/security/UnresolvedPermission.java
+++ b/libcore/security/src/main/java/java/security/UnresolvedPermission.java
@@ -15,27 +15,18 @@
* limitations under the License.
*/
-/**
-* @author Alexey V. Varlamov
-* @version $Revision$
-*/
-
package java.security;
import java.io.ByteArrayInputStream;
import java.io.IOException;
-import java.io.InvalidObjectException;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
-import java.io.ObjectStreamField;
import java.io.Serializable;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
-import java.util.ArrayList;
-import java.util.List;
import org.apache.harmony.security.fortress.PolicyUtils;
import org.apache.harmony.security.internal.nls.Messages;
@@ -46,24 +37,17 @@
* Policy}. {@code UnresolvedPermission}s contain all information to be replaced
* by a concrete typed {@code Permission} right before the access checks are
* performed.
- *
- * @since Android 1.0
*/
public final class UnresolvedPermission extends Permission
implements Serializable {
private static final long serialVersionUID = -4821973115467008846L;
- private static final ObjectStreamField serialPersistentFields[] = {
- new ObjectStreamField("type", String.class), //$NON-NLS-1$
- new ObjectStreamField("name", String.class), //$NON-NLS-1$
- new ObjectStreamField("actions", String.class), }; //$NON-NLS-1$
-
- // Target name
- private transient String targetName;
-
- //Target actions
- private transient String targetActions;
+ private String type;
+
+ private String name;
+
+ private String actions;
// The signer certificates
private transient Certificate[] targetCerts;
@@ -75,7 +59,7 @@
* Constructs a new instance of {@code UnresolvedPermission}. The supplied
* parameters are used when this instance is resolved to the concrete
* {@code Permission}.
- *
+ *
* @param type
* the fully qualified class name of the permission this class is
* resolved to.
@@ -90,26 +74,17 @@
* maybe {@code null}.
* @throws NullPointerException
* if type is {@code null}.
- * @since Android 1.0
*/
public UnresolvedPermission(String type, String name, String actions,
Certificate[] certs) {
super(type);
checkType(type);
- targetName = name;
- targetActions = actions;
- if (certs != null && certs.length != 0) {
- //TODO filter non-signer certificates ???
- List tmp = new ArrayList();
- for (int i = 0; i < certs.length; i++) {
- if (certs[i] != null) {
- tmp.add(certs[i]);
- }
- }
- if (tmp.size() != 0) {
- targetCerts = (Certificate[])tmp.toArray(
- new Certificate[tmp.size()]);
- }
+ this.type = type;
+ this.name = name;
+ this.actions = actions;
+ if (certs != null) {
+ this.targetCerts = new Certificate[certs.length];
+ System.arraycopy(certs, 0, targetCerts, 0, certs.length);
}
hash = 0;
}
@@ -136,52 +111,105 @@
* instance of {@code UnresolvedPermission}, the two {@code
* UnresolvedPermission}s must refer to the same type and must have the same
* name, the same actions and certificates.
- *
+ *
* @param obj
* object to be compared for equality with this {@code
* UnresolvedPermission}.
* @return {@code true} if the specified object is equal to this {@code
* UnresolvedPermission}, otherwise {@code false}.
- * @since Android 1.0
*/
+ @Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof UnresolvedPermission) {
- UnresolvedPermission that = (UnresolvedPermission)obj;
+ UnresolvedPermission that = (UnresolvedPermission) obj;
if (getName().equals(that.getName())
- && (targetName == null ? that.targetName == null
- : targetName.equals(that.targetName))
- && (targetActions == null ? that.targetActions == null
- : targetActions.equals(that.targetActions))
- && (PolicyUtils.matchSubset(targetCerts, that.targetCerts)
- && PolicyUtils.matchSubset(that.targetCerts, targetCerts))) {
+ && (name == null ? that.name == null : name
+ .equals(that.name))
+ && (actions == null ? that.actions == null : actions
+ .equals(that.actions))
+ && equalsCertificates(this.targetCerts, that.targetCerts)) {
return true;
}
}
return false;
}
+ /*
+ * check whether given array of certificates are equivalent
+ */
+ private boolean equalsCertificates(Certificate[] certs1,
+ Certificate[] certs2) {
+ if (certs1 == null || certs2 == null) {
+ return certs1 == certs2;
+ }
+
+ int length = certs1.length;
+ if (length != certs2.length) {
+ return false;
+ }
+
+ if (length > 0) {
+ boolean found;
+ for (int i = 0; i < length; i++) {
+ // Skip the checking for null
+ if(certs1[i] == null){
+ continue;
+ }
+ found = false;
+ for (int j = 0; j < length; j++) {
+ if (certs1[i].equals(certs2[j])) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ return false;
+ }
+ }
+
+ for (int i = 0; i < length; i++) {
+ if(certs2[i] == null){
+ continue;
+ }
+ found = false;
+ for (int j = 0; j < length; j++) {
+ if (certs2[i].equals(certs1[j])) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
/**
* Returns the hash code value for this {@code UnresolvedPermission}.
* Returns the same hash code for {@code UnresolvedPermission}s that are
* equal to each other as required by the general contract of
* {@link Object#hashCode}.
- *
+ *
* @return the hash code value for this {@code UnresolvedPermission}.
* @see Object#equals(Object)
* @see UnresolvedPermission#equals(Object)
- * @since Android 1.0
*/
+ @Override
public int hashCode() {
if (hash == 0) {
hash = getName().hashCode();
- if (targetName != null) {
- hash ^= targetName.hashCode();
+ if (name != null) {
+ hash ^= name.hashCode();
}
- if (targetActions != null) {
- hash ^= targetActions.hashCode();
+ if (actions != null) {
+ hash ^= actions.hashCode();
}
}
return hash;
@@ -191,10 +219,10 @@
* Returns an empty string since there are no actions allowed for {@code
* UnresolvedPermission}. The actions, specified in the constructor, are
* used when the concrete permission is resolved and created.
- *
+ *
* @return an empty string, indicating that there are no actions.
- * @since Android 1.0
*/
+ @Override
public String getActions() {
return ""; //$NON-NLS-1$
}
@@ -202,34 +230,31 @@
/**
* Returns the name of the permission this {@code UnresolvedPermission} is
* resolved to.
- *
+ *
* @return the name of the permission this {@code UnresolvedPermission} is
* resolved to.
- * @since Android 1.0
*/
public String getUnresolvedName() {
- return targetName;
+ return name;
}
/**
* Returns the actions of the permission this {@code UnresolvedPermission}
* is resolved to.
- *
+ *
* @return the actions of the permission this {@code UnresolvedPermission}
* is resolved to.
- * @since Android 1.0
*/
public String getUnresolvedActions() {
- return targetActions;
+ return actions;
}
/**
* Returns the fully qualified class name of the permission this {@code
* UnresolvedPermission} is resolved to.
- *
+ *
* @return the fully qualified class name of the permission this {@code
* UnresolvedPermission} is resolved to.
- * @since Android 1.0
*/
public String getUnresolvedType() {
return super.getName();
@@ -238,10 +263,9 @@
/**
* Returns the certificates of the permission this {@code
* UnresolvedPermission} is resolved to.
- *
+ *
* @return the certificates of the permission this {@code
* UnresolvedPermission} is resolved to.
- * @since Android 1.0
*/
public Certificate[] getUnresolvedCerts() {
if (targetCerts != null) {
@@ -261,13 +285,12 @@
* UnresolvedPermissions (if any) against the passed instance. Successfully
* resolved permissions (if any) are taken into account during further
* processing.
- * </p>
- *
+ *
* @param permission
* the permission to check.
* @return always {@code false}
- * @since Android 1.0
*/
+ @Override
public boolean implies(Permission permission) {
return false;
}
@@ -276,23 +299,23 @@
* Returns a string containing a concise, human-readable description of this
* {@code UnresolvedPermission} including its target name and its target
* actions.
- *
+ *
* @return a printable representation for this {@code UnresolvedPermission}.
- * @since Android 1.0
*/
+ @Override
public String toString() {
- return "(unresolved " + getName() + " " + targetName + " " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- + targetActions + ")"; //$NON-NLS-1$
+ return "(unresolved " + type + " " + name + " " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ + actions + ")"; //$NON-NLS-1$
}
/**
* Returns a new {@code PermissionCollection} for holding {@code
* UnresolvedPermission} objects.
- *
+ *
* @return a new PermissionCollection for holding {@code
* UnresolvedPermission} objects.
- * @since Android 1.0
*/
+ @Override
public PermissionCollection newPermissionCollection() {
return new UnresolvedPermissionCollection();
}
@@ -306,16 +329,12 @@
* per {@code getUnresolvedCerts()}) among the passed collection of signers.
* If it does, a zero, one, and/or two-argument constructor is tried to
* instantiate a new permission, which is then returned.
- * </p>
* <p>
* If an appropriate constructor is not available or the class is improperly
* signed, {@code null} is returned.
- * </p>
- *
+ *
* @param targetType
* - a target class instance, must not be {@code null}
- * @param signers
- * - actual signers of the targetType
* @return resolved permission or null
*/
Permission resolve(Class targetType) {
@@ -323,8 +342,8 @@
if (PolicyUtils.matchSubset(targetCerts, targetType.getSigners())) {
try {
return PolicyUtils.instantiatePermission(targetType,
- targetName,
- targetActions);
+ name,
+ actions);
} catch (Exception ignore) {
//TODO log warning?
}
@@ -333,8 +352,6 @@
}
/**
- * @com.intel.drl.spec_ref
- *
* Outputs {@code type},{@code name},{@code actions}
* fields via default mechanism; next manually writes certificates in the
* following format: <br>
@@ -353,11 +370,7 @@
* @see <a href="http://java.sun.com/j2se/1.5.0/docs/api/serialized-form.html#java.security.UnresolvedPermission">Java Spec</a>
*/
private void writeObject(ObjectOutputStream out) throws IOException {
- ObjectOutputStream.PutField fields = out.putFields();
- fields.put("type", getUnresolvedType()); //$NON-NLS-1$
- fields.put("name", getUnresolvedName()); //$NON-NLS-1$
- fields.put("actions", getUnresolvedActions()); //$NON-NLS-1$
- out.writeFields();
+ out.defaultWriteObject();
if (targetCerts == null) {
out.writeInt(0);
} else {
@@ -378,19 +391,12 @@
}
/**
- * @com.intel.drl.spec_ref
- *
* Reads the object from stream and checks target type for validity.
*/
private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException {
- checkType(getUnresolvedType());
- ObjectInputStream.GetField fields = in.readFields();
- if (!getUnresolvedType().equals(fields.get("type", null))) { //$NON-NLS-1$
- throw new InvalidObjectException(Messages.getString("security.31")); //$NON-NLS-1$
- }
- targetName = (String)fields.get("name", null); //$NON-NLS-1$
- targetActions = (String)fields.get("actions", null); //$NON-NLS-1$
+ in.defaultReadObject();
+ checkType(getUnresolvedType());
int certNumber = in.readInt();
if (certNumber != 0) {
targetCerts = new Certificate[certNumber];
diff --git a/libcore/security/src/main/java/java/security/UnresolvedPermissionCollection.java b/libcore/security/src/main/java/java/security/UnresolvedPermissionCollection.java
index a43a54f..3a6ba92 100644
--- a/libcore/security/src/main/java/java/security/UnresolvedPermissionCollection.java
+++ b/libcore/security/src/main/java/java/security/UnresolvedPermissionCollection.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Alexey V. Varlamov
-* @version $Revision$
-*/
-
package java.security;
import java.io.IOException;
@@ -66,7 +61,6 @@
* @throws IllegalArgumentException
* if {@code permission} is {@code null} or not an {@code
* UnresolvedPermission}.
- * @since Android 1.0
*/
public void add(Permission permission) {
if (isReadOnly()) {
@@ -101,7 +95,6 @@
*
* @return always {@code false}
* @see UnresolvedPermission#implies(Permission).
- * @since Android 1.0
*/
public boolean implies(Permission permission) {
return false;
@@ -159,15 +152,14 @@
}
/**
- * @com.intel.drl.spec_ref
- *
* Output fields via default mechanism.
*/
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
Hashtable permissions = new Hashtable();
- for (Iterator iter = klasses.keySet().iterator(); iter.hasNext();) {
- String key = (String)iter.next();
- permissions.put(key, new Vector(((Collection)klasses.get(key))));
+ for (Iterator iter = klasses.entrySet().iterator(); iter.hasNext();) {
+ Map.Entry entry = (Map.Entry) iter.next();
+ String key = (String) entry.getKey();
+ permissions.put(key, new Vector(((Collection) entry.getValue())));
}
ObjectOutputStream.PutField fields = out.putFields();
fields.put("permissions", permissions); //$NON-NLS-1$
@@ -175,8 +167,6 @@
}
/**
- * @com.intel.drl.spec_ref
- *
* Reads the object from stream and checks elements grouping for validity.
*/
private void readObject(java.io.ObjectInputStream in) throws IOException,
@@ -185,20 +175,23 @@
Map permissions = (Map)fields.get("permissions", null); //$NON-NLS-1$
klasses = new HashMap();
synchronized (klasses) {
- for (Iterator iter = permissions.keySet().iterator(); iter
- .hasNext();) {
- String key = (String)iter.next();
- Collection values = (Collection)permissions.get(key);
- for (Iterator iterator = values.iterator(); iterator.hasNext();) {
- UnresolvedPermission element = (UnresolvedPermission)iterator
- .next();
- if (!element.getName().equals(key)) {
- throw new InvalidObjectException(
- Messages.getString("security.22")); //$NON-NLS-1$
- }
- }
- klasses.put(key, new HashSet(values));
- }
+ for (Iterator iter = permissions.entrySet().iterator(); iter
+ .hasNext();) {
+ Map.Entry entry = (Map.Entry) iter.next();
+ String key = (String) entry.getKey();
+ Collection values = (Collection) entry.getValue();
+
+ for (Iterator iterator = values.iterator(); iterator.hasNext();) {
+ UnresolvedPermission element =
+ (UnresolvedPermission) iterator.next();
+
+ if (!element.getName().equals(key)) {
+ throw new InvalidObjectException(
+ Messages.getString("security.22")); //$NON-NLS-1$
+ }
+ }
+ klasses.put(key, new HashSet(values));
+ }
}
}
}
\ No newline at end of file
diff --git a/libcore/security/src/main/java/java/security/acl/Acl.java b/libcore/security/src/main/java/java/security/acl/Acl.java
index 35c92fc..88dd9f0 100644
--- a/libcore/security/src/main/java/java/security/acl/Acl.java
+++ b/libcore/security/src/main/java/java/security/acl/Acl.java
@@ -24,17 +24,15 @@
* The <i>Access Control List</i> (<b>ACL</b>) interface definition.
* <p>
* An ACL is a set of {@link AclEntry} objects.
- * </p>
* <p>
* An {@code AclEntry} is a list of {@link Permission}s that are granted
* (<i>positive</i>) or denied
* (<i>negative</i>) to a {@link Principal}.
- * </p>
* <p>
- * An {@code Acl} has a list of owners ({@link Owner}) which are principals as well {@code
- * Principal}. Only those principals which are the {@code Acl}'s owners are allowed to modify the {@code
+ * An {@code Acl} has a list of owners ({@link Owner}) which are principals as
+ * well {@code Principal}. Only those principals which are the {@code Acl}'s
+ * owners are allowed to modify the {@code
* Acl}.
- * </p>
* <p>
* The <i>ACL</i> has to conform to the following rules:
* <ul>
@@ -49,9 +47,6 @@
* <li>If there is no {@code AclEntry} associated with a specific {@code
* Principal}, then it is interpreted as an empty list of permissions.</li>
* </ul>
- * </p>
- *
- * @since Android 1.0
*/
public interface Acl extends Owner {
@@ -65,7 +60,6 @@
* @throws NotOwnerException
* if the invoking {@code Principal} is not an owner of this
* <i>ACL</i>.
- * @since Android 1.0
*/
void setName(Principal caller, String name) throws NotOwnerException;
@@ -73,7 +67,6 @@
* Returns the name of this <i>ACL</i> instance.
*
* @return the name of this <i>ACL</i> instance.
- * @since Android 1.0
*/
String getName();
@@ -82,18 +75,16 @@
* <p>
* If the <i>ACL</i> already has an {@code AclEntry} of the same type (<i>
* positive</i> or <i>negative</i>) and principal, then the new entry is not added.
- * </p>
- *
+ *
* @param caller
* the invoking {@code Principal}.
* @param entry
* the ACL entry to add.
- * @return {@code true} if the entry is added, {@code false} if there is already an entry of
- * the same type for the same principal
+ * @return {@code true} if the entry is added, {@code false} if there is
+ * already an entry of the same type for the same principal
* @throws NotOwnerException
* if the invoking {@code Principal} is not an owner of this
* <i>ACL</i>.
- * @since Android 1.0
*/
boolean addEntry(Principal caller, AclEntry entry) throws NotOwnerException;
@@ -104,12 +95,11 @@
* the invoking {@code Principal}.
* @param entry
* the ACL entry to remove.
- * @return {@code true} if the entry is removed, {@code false} if the entry is not in this
- * <i>ACL</i>.
+ * @return {@code true} if the entry is removed, {@code false} if the entry
+ * is not in this <i>ACL</i>.
* @throws NotOwnerException
* if the invoking {@code Principal} is not an owner of this
* <i>ACL</i>.
- * @since Android 1.0
*/
boolean removeEntry(Principal caller, AclEntry entry)
throws NotOwnerException;
@@ -120,7 +110,6 @@
* <p>
* If the specified principal has no entry in this ACL, an empty set is
* returned.
- * </p>
* <p>
* The allowed permissions are collected according to the following rules:
* <ul>
@@ -136,12 +125,10 @@
* permissions override the group's negative permissions and the negative
* individual permissions override the grpup's positive permissions.</li>
* </ul>
- * </p>
- *
+ *
* @param user
* the principal to get the allowed permissions for.
* @return the set of allowed permissions for the specified principal.
- * @since Android 1.0
*/
Enumeration<Permission> getPermissions(Principal user);
@@ -151,7 +138,6 @@
*
* @return an {@code Enumeration} of the {@code AclEntry} of this
* <i>ACL</i>.
- * @since Android 1.0
*/
Enumeration<AclEntry> entries();
@@ -161,15 +147,14 @@
* <p>
* The list of granted permissions is determined according to the rules
* specified by {@code getPermissions}.
- * </p>
- *
+ *
* @param principal
* the principal the check the permissions for.
* @param permission
* the permission to check for the principal.
- * @return {@code true} if the principal is granted the permission, otherwise {@code false}.
+ * @return {@code true} if the principal is granted the permission,
+ * otherwise {@code false}.
* @see #getPermissions(Principal)
- * @since Android 1.0
*/
boolean checkPermission(Principal principal, Permission permission);
@@ -177,7 +162,6 @@
* Returns the string representation of this ACL.
*
* @return the string representation of this ACL.
- * @since Android 1.0
*/
String toString();
}
diff --git a/libcore/security/src/main/java/java/security/acl/AclEntry.java b/libcore/security/src/main/java/java/security/acl/AclEntry.java
index 7a5b722..fe2fb3a 100644
--- a/libcore/security/src/main/java/java/security/acl/AclEntry.java
+++ b/libcore/security/src/main/java/java/security/acl/AclEntry.java
@@ -25,9 +25,6 @@
* <p>
* An {@code AclEntry} is a list of the {@link Permission}s that are
* granted (<i>positive</i>) or denied (<i>negative</i>) to a {@link Principal}.
- * </p>
- *
- * @since Android 1.0
*/
public interface AclEntry extends Cloneable {
@@ -35,13 +32,11 @@
* Set the principal for this ACL entry.
* <p>
* The principal for an ACL entry can only be set once.
- * </p>
- *
+ *
* @param user
* the principal for this ACL entry.
* @return {@code true} on success, {@code false} if there is a principal already set for
* this entry.
- * @since Android 1.0
*/
boolean setPrincipal(Principal user);
@@ -49,7 +44,6 @@
* Returns the principal of this ACL entry.
*
* @return the principal of this ACL entry, or null if none is set.
- * @since Android 1.0
*/
Principal getPrincipal();
@@ -58,13 +52,9 @@
* <p>
* The permissions in this ACL entry will be denied to the principal
* associated with this entry.
- * </p>
* <p>
* Note: An ACL entry is <i>positive</i> by default and can only become
* <i>negative</i> by calling this method.
- * </p>
- *
- * @since Android 1.0
*/
void setNegativePermissions();
@@ -72,7 +62,6 @@
* Returns whether this ACL entry is <i>negative</i>.
*
* @return {@code true} if this ACL entry is negative, {@code false} if it's positive.
- * @since Android 1.0
*/
boolean isNegative();
@@ -83,7 +72,6 @@
* the permission to be added.
* @return {@code true} if the specified permission is added, {@code false} if the
* permission was already in this entry.
- * @since Android 1.0
*/
boolean addPermission(Permission permission);
@@ -94,7 +82,6 @@
* the permission to be removed.
* @return {@code true} if the permission is removed, {@code false} if the permission was
* not in this entry.
- * @since Android 1.0
*/
boolean removePermission(Permission permission);
@@ -104,7 +91,6 @@
* @param permission
* the permission to check.
* @return {@code true} if the permission is in this entry, otherwise {@code false}.
- * @since Android 1.0
*/
boolean checkPermission(Permission permission);
@@ -112,7 +98,6 @@
* Returns the list of permissions of this ACL entry.
*
* @return the list of permissions of this ACL entry,
- * @since Android 1.0
*/
Enumeration<Permission> permissions();
@@ -120,7 +105,6 @@
* Returns the string representation of this ACL entry.
*
* @return the string representation of this ACL entry.
- * @since Android 1.0
*/
String toString();
@@ -128,7 +112,6 @@
* Clones this ACL entry instance.
*
* @return a copy of this entry.
- * @since Android 1.0
*/
Object clone();
diff --git a/libcore/security/src/main/java/java/security/acl/AclNotFoundException.java b/libcore/security/src/main/java/java/security/acl/AclNotFoundException.java
index c8d4208..59b9045 100644
--- a/libcore/security/src/main/java/java/security/acl/AclNotFoundException.java
+++ b/libcore/security/src/main/java/java/security/acl/AclNotFoundException.java
@@ -20,18 +20,13 @@
/**
* The exception, that is thrown when a reference to a non-existent <i>Access
* Control List</i> (ACL) is made.
- *
- * @since Android 1.0
*/
-
public class AclNotFoundException extends Exception {
private static final long serialVersionUID = 5684295034092681791L;
/**
* Creates a new {@code AclNotFoundException}.
- *
- * @since Android 1.0
*/
public AclNotFoundException() {
diff --git a/libcore/security/src/main/java/java/security/acl/Group.java b/libcore/security/src/main/java/java/security/acl/Group.java
index 16898e6..7452181 100644
--- a/libcore/security/src/main/java/java/security/acl/Group.java
+++ b/libcore/security/src/main/java/java/security/acl/Group.java
@@ -24,8 +24,6 @@
* A {@code Principal} that represents a group of principals.
*
* @see Principal
- *
- * @since Android 1.0
*/
public interface Group extends Principal {
@@ -35,7 +33,6 @@
* @param user
* the member to add.
* @return {@code true} if the member was added, {@code false} if it was already a member.
- * @since Android 1.0
*/
boolean addMember(Principal user);
@@ -45,7 +42,6 @@
* @param user
* the member to remove.
* @return {@code true} if the member was removed, {@code false} if it was not a member.
- * @since Android 1.0
*/
boolean removeMember(Principal user);
@@ -55,7 +51,6 @@
* @param member
* the principal to check.
* @return {@code true} if the principal is a member, otherwise {@code false}.
- * @since Android 1.0
*/
boolean isMember(Principal member);
@@ -63,7 +58,6 @@
* Returns the members of this group.
*
* @return the members of this group.
- * @since Android 1.0
*/
Enumeration<? extends Principal> members();
diff --git a/libcore/security/src/main/java/java/security/acl/LastOwnerException.java b/libcore/security/src/main/java/java/security/acl/LastOwnerException.java
index 11c235f..f947f22 100644
--- a/libcore/security/src/main/java/java/security/acl/LastOwnerException.java
+++ b/libcore/security/src/main/java/java/security/acl/LastOwnerException.java
@@ -18,12 +18,10 @@
package java.security.acl;
/**
- * The exception that is thrown when an attempt is made to remove the
+ * The exception that is thrown when an attempt is made to remove the
* the last {@code Owner} from an {@code Owner}.
- *
+ *
* @see Owner
- *
- * @since Android 1.0
*/
public class LastOwnerException extends Exception {
@@ -31,9 +29,7 @@
/**
* Creates a new {@code LastOwnerException}.
- *
- * @since Android 1.0
*/
public LastOwnerException() {
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/acl/NotOwnerException.java b/libcore/security/src/main/java/java/security/acl/NotOwnerException.java
index 081bdea..c7de8c9 100644
--- a/libcore/security/src/main/java/java/security/acl/NotOwnerException.java
+++ b/libcore/security/src/main/java/java/security/acl/NotOwnerException.java
@@ -19,13 +19,11 @@
/**
* The exception that is thrown when an action that requires ownership is
- * attempted by a principal that is not an owner of the object for which
- * ownership is required.
+ * attempted by a principal that is not an owner of the object for which
+ * ownership is required.
*
* @see Acl
* @see Owner
- *
- * @since Android 1.0
*/
public class NotOwnerException extends Exception {
@@ -33,9 +31,7 @@
/**
* Creates a new {@code NotOwnerException}.
- *
- * @since Android 1.0
*/
public NotOwnerException() {
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/acl/Owner.java b/libcore/security/src/main/java/java/security/acl/Owner.java
index 335dc84..c392e2f 100644
--- a/libcore/security/src/main/java/java/security/acl/Owner.java
+++ b/libcore/security/src/main/java/java/security/acl/Owner.java
@@ -24,7 +24,6 @@
*
* @see Acl
* @see Principal
- * @since Android 1.0
*/
public interface Owner {
@@ -38,7 +37,6 @@
* @return {@code true} if the owner was added, {@code false} if it was already an owner.
* @throws NotOwnerException
* if the invoking principal is not an owner.
- * @since Android 1.0
*/
boolean addOwner(Principal caller, Principal owner)
throws NotOwnerException;
@@ -56,7 +54,6 @@
* @throws LastOwnerException
* if the owner to be removed is the last owner and hence removing it
* would make this object owner-less.
- * @since Android 1.0
*/
boolean deleteOwner(Principal caller, Principal owner)
throws NotOwnerException, LastOwnerException;
@@ -67,7 +64,6 @@
* @param owner
* the principal to check.
* @return {@code true} if the specified principal is an owner, otherwise {@code false}.
- * @since Android 1.0
*/
boolean isOwner(Principal owner);
}
diff --git a/libcore/security/src/main/java/java/security/acl/Permission.java b/libcore/security/src/main/java/java/security/acl/Permission.java
index 0d6e22c..f2ee251 100644
--- a/libcore/security/src/main/java/java/security/acl/Permission.java
+++ b/libcore/security/src/main/java/java/security/acl/Permission.java
@@ -22,9 +22,6 @@
* <p>
* It can be granted or denied to a {@link java.security.Principal Principal}
* using an {@link Acl}.
- * </p>
- *
- * @since Android 1.0
*/
public interface Permission {
@@ -36,7 +33,6 @@
* the permission object to compare to this permission.
* @return true if the specified permission object is equal to this, false
* if not.
- * @since Android 1.0
*/
boolean equals(Object another);
@@ -44,7 +40,6 @@
* Returns the string representation of this permission.
*
* @return the string representation of this permission.
- * @since Android 1.0
*/
String toString();
}
diff --git a/libcore/security/src/main/java/java/security/cert/CRL.java b/libcore/security/src/main/java/java/security/cert/CRL.java
index b0f3e30..8153853 100644
--- a/libcore/security/src/main/java/java/security/cert/CRL.java
+++ b/libcore/security/src/main/java/java/security/cert/CRL.java
@@ -23,7 +23,6 @@
* expired and consequently has become invalid.
*
* @see CertificateFactory
- * @since Android 1.0
*/
public abstract class CRL {
// The CRL type
@@ -31,10 +30,9 @@
/**
* Creates a new certificate revocation list of the specified type.
- *
+ *
* @param type
* the type for the CRL.
- * @since Android 1.0
*/
protected CRL(String type) {
this.type = type;
@@ -42,9 +40,8 @@
/**
* Returns the type of this CRL.
- *
+ *
* @return the type of this CRL.
- * @since Android 1.0
*/
public final String getType() {
return type;
@@ -52,20 +49,18 @@
/**
* Returns whether the specified certificate is revoked by this CRL.
- *
+ *
* @param cert
* the certificate to check.
* @return {@code true} if the certificate is revoked by this CRL, otherwise
* {@code false}.
- * @since Android 1.0
*/
public abstract boolean isRevoked(Certificate cert);
/**
* Returns the string representation of this instance.
- *
+ *
* @return the string representation of this instance.
- * @since Android 1.0
*/
public abstract String toString();
}
diff --git a/libcore/security/src/main/java/java/security/cert/CRLException.java b/libcore/security/src/main/java/java/security/cert/CRLException.java
index 625d7d3..01e2071 100644
--- a/libcore/security/src/main/java/java/security/cert/CRLException.java
+++ b/libcore/security/src/main/java/java/security/cert/CRLException.java
@@ -15,19 +15,12 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
package java.security.cert;
import java.security.GeneralSecurityException;
/**
* The exception that is thrown if errors occur during handling of {@code CRL}s.
- *
- * @since Android 1.0
*/
public class CRLException extends GeneralSecurityException {
@@ -38,7 +31,6 @@
*
* @param msg
* the detail message for this exception.
- * @since Android 1.0
*/
public CRLException(String msg) {
super(msg);
@@ -46,8 +38,6 @@
/**
* Creates a new {@code CRLException}.
- *
- * @since Android 1.0
*/
public CRLException() {
}
@@ -59,7 +49,6 @@
* the detail message for this exception.
* @param cause
* the cause for this exception.
- * @since Android 1.0
*/
public CRLException(String message, Throwable cause) {
super(message, cause);
@@ -70,7 +59,6 @@
*
* @param cause
* the cause for this exception.
- * @since Android 1.0
*/
public CRLException(Throwable cause) {
super(cause);
diff --git a/libcore/security/src/main/java/java/security/cert/CRLSelector.java b/libcore/security/src/main/java/java/security/cert/CRLSelector.java
index ee2d39e..5b14446 100644
--- a/libcore/security/src/main/java/java/security/cert/CRLSelector.java
+++ b/libcore/security/src/main/java/java/security/cert/CRLSelector.java
@@ -23,11 +23,9 @@
* <p>
* The implementations of this interface are typically used to define the
* criteria for selecting {@code CRL}s from a {@code CertStore}.
- * </p>
*
* @see CertStore
* @see CRL
- * @since Android 1.0
*/
public interface CRLSelector extends Cloneable {
@@ -35,7 +33,6 @@
* Clones this {@code CRLSelector} instance.
*
* @return the cloned instance.
- * @since Android 1.0
*/
public Object clone();
@@ -47,7 +44,6 @@
* the CRL to be evaluated.
* @return {@code true} if the CRL matches the criteria, {@code false}
* otherwise.
- * @since Android 1.0
*/
public boolean match(CRL crl);
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/cert/CertPath.java b/libcore/security/src/main/java/java/security/cert/CertPath.java
index 2874a4d..e9d049b 100644
--- a/libcore/security/src/main/java/java/security/cert/CertPath.java
+++ b/libcore/security/src/main/java/java/security/cert/CertPath.java
@@ -33,16 +33,12 @@
* <p>
* A {@code CertPath} can be represented as a byte array in at least one
* supported encoding scheme (i.e. PkiPath or PKCS7) when serialized.
- * </p>
* <p>
* When a {@code List} of the certificates is obtained it must be immutable.
- * </p>
* <p>
* A {@code CertPath} must be thread-safe without requiring coordinated access.
- * </p>
- *
+ *
* @see Certificate
- * @since Android 1.0
*/
public abstract class CertPath implements Serializable {
@@ -53,10 +49,9 @@
/**
* Creates a new {@code CertPath} instance for the specified certificate
* type.
- *
+ *
* @param type
* the certificate type.
- * @since Android 1.0
*/
protected CertPath(String type) {
this.type = type;
@@ -64,9 +59,8 @@
/**
* Returns the type of {@code Certificate} in this instance.
- *
+ *
* @return the certificate type.
- * @since Android 1.0
*/
public String getType() {
return type;
@@ -76,13 +70,11 @@
* Returns {@code true} if {@code Certificate}s in the list are the same
* type and the lists are equal (and by implication the certificates
* contained within are the same).
- *
+ *
* @param other
* {@code CertPath} to be compared for equality.
* @return {@code true} if the object are equal, {@code false} otherwise.
- * @since Android 1.0
*/
- @Override
public boolean equals(Object other) {
if (this == other) {
return true;
@@ -99,14 +91,14 @@
}
/**
- * Overrides {@code Object.hashCode()}. The function is defined as follows: <br>
+ * Overrides {@code Object.hashCode()}. The function is defined as follows:
+ * <pre>
* {@code hashCode = 31 * path.getType().hashCode() +
- * path.getCertificates().hashCode();}</br> </p>
- *
+ * path.getCertificates().hashCode();}
+ * </pre>
+ *
* @return the hash code for this instance.
- * @since Android 1.0
*/
- @Override
public int hashCode() {
int hash = getType().hashCode();
hash = hash*31 + getCertificates().hashCode();
@@ -115,13 +107,13 @@
/**
* Returns a {@code String} representation of this {@code CertPath}
- * instance.
- *
+ * instance. It is the result of calling {@code toString} on all {@code
+ * Certificate}s in the {@code List}.
+ *
* @return a string representation of this instance.
- * @since Android 1.0
*/
public String toString() {
- StringBuffer sb = new StringBuffer(getType());
+ StringBuilder sb = new StringBuilder(getType());
sb.append(" Cert Path, len="); //$NON-NLS-1$
sb.append(getCertificates().size());
sb.append(": [\n"); //$NON-NLS-1$
@@ -144,7 +136,6 @@
* in the {@code CertPath}.
*
* @return a list of {@code Certificate}s in the {@code CertPath}.
- * @since Android 1.0
*/
public abstract List<? extends Certificate> getCertificates();
@@ -154,7 +145,6 @@
* @return default encoding of the {@code CertPath}.
* @throws CertificateEncodingException
* if the encoding fails.
- * @since Android 1.0
*/
public abstract byte[] getEncoded()
throws CertificateEncodingException;
@@ -167,7 +157,6 @@
* @return default encoding of the {@code CertPath}.
* @throws CertificateEncodingException
* if the encoding fails.
- * @since Android 1.0
*/
public abstract byte[] getEncoded(String encoding)
throws CertificateEncodingException;
@@ -177,17 +166,15 @@
* representation of the certificate path.
*
* @return {@code Iterator} over supported encodings (as {@code String}s).
- * @since Android 1.0
*/
public abstract Iterator<String> getEncodings();
/**
* Returns an alternate object to be serialized.
- *
+ *
* @return an alternate object to be serialized.
* @throws ObjectStreamException
* if the creation of the alternate object fails.
- * @since Android 1.0
*/
protected Object writeReplace() throws ObjectStreamException {
try {
@@ -201,8 +188,6 @@
/**
* The alternate {@code Serializable} class to be used for serialization and
* deserialization on {@code CertPath} objects.
- *
- * @since Android 1.0
*/
protected static class CertPathRep implements Serializable {
@@ -222,12 +207,11 @@
/**
* Creates a new {@code CertPathRep} instance with the specified type
* and encoded data.
- *
+ *
* @param type
* the certificate type.
* @param data
* the encoded data.
- * @since Android 1.0
*/
protected CertPathRep(String type, byte[] data) {
this.type = type;
@@ -237,11 +221,10 @@
/**
* Deserializes a {@code CertPath} from a serialized {@code CertPathRep}
* object.
- *
+ *
* @return the deserialized {@code CertPath}.
* @throws ObjectStreamException
* if deserialization fails.
- * @since Android 1.0
*/
protected Object readResolve() throws ObjectStreamException {
try {
diff --git a/libcore/security/src/main/java/java/security/cert/CertPathBuilder.java b/libcore/security/src/main/java/java/security/cert/CertPathBuilder.java
index 47eac13..8daa741 100644
--- a/libcore/security/src/main/java/java/security/cert/CertPathBuilder.java
+++ b/libcore/security/src/main/java/java/security/cert/CertPathBuilder.java
@@ -31,8 +31,6 @@
/**
* This class implements the functionality of a builder for an unverified
* <i>Certification Path</i>s from a specified certificate to a trust anchor.
- *
- * @since Android 1.0
*/
public class CertPathBuilder {
@@ -60,14 +58,13 @@
/**
* Creates a new {@code CertPathBuilder}.
- *
+ *
* @param builderSpi
* the implementation delegate.
* @param provider
* the provider.
* @param algorithm
* the desired algorithm available at the provider.
- * @since Android 1.0
*/
protected CertPathBuilder(CertPathBuilderSpi builderSpi, Provider provider,
String algorithm) {
@@ -78,9 +75,8 @@
/**
* Returns the algorithm name of this instance.
- *
+ *
* @return the algorithm name of this instance.
- * @since Android 1.0
*/
public final String getAlgorithm() {
return algorithm;
@@ -88,9 +84,8 @@
/**
* Returns the provider of this instance.
- *
+ *
* @return the provider of this instance.
- * @since Android 1.0
*/
public final Provider getProvider() {
return provider;
@@ -107,7 +102,6 @@
* if the algorithm is {@code null}.
* @throws NoSuchAlgorithmException
* if no installed provider can provide the algorithm.
- * @since Android 1.0
*/
public static CertPathBuilder getInstance(String algorithm)
throws NoSuchAlgorithmException {
@@ -138,7 +132,6 @@
* if algorithm is {@code null}.
* @throws IllegalArgumentException
* if provider is {@code null} or empty.
- * @since Android 1.0
*/
public static CertPathBuilder getInstance(String algorithm, String provider)
throws NoSuchAlgorithmException, NoSuchProviderException {
@@ -168,7 +161,6 @@
* if provider is {@code null}.
* @throws NullPointerException
* if algorithm is {@code null}.
- * @since Android 1.0
*/
public static CertPathBuilder getInstance(String algorithm,
Provider provider) throws NoSuchAlgorithmException {
@@ -187,7 +179,7 @@
/**
* Builds a certification path with the specified algorithm parameters.
- *
+ *
* @param params
* the algorithm parameters.
* @return the built certification path.
@@ -197,7 +189,6 @@
* if the specified parameters cannot be used to build with this
* builder.
* @see CertPathBuilderResult
- * @since Android 1.0
*/
public final CertPathBuilderResult build(CertPathParameters params)
throws CertPathBuilderException, InvalidAlgorithmParameterException {
@@ -207,11 +198,10 @@
/**
* Returns the default {@code CertPathBuilder} type from the <i>Security
* Properties</i>.
- *
+ *
* @return the default {@code CertPathBuilder} type from the <i>Security
* Properties</i>, or the string "{@code PKIX}" if it cannot be
* determined.
- * @since Android 1.0
*/
public static final String getDefaultType() {
String defaultType = AccessController
@@ -222,4 +212,4 @@
});
return (defaultType != null ? defaultType : DEFAULTPROPERTY);
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/cert/CertPathBuilderException.java b/libcore/security/src/main/java/java/security/cert/CertPathBuilderException.java
index b957291..58a4a60 100644
--- a/libcore/security/src/main/java/java/security/cert/CertPathBuilderException.java
+++ b/libcore/security/src/main/java/java/security/cert/CertPathBuilderException.java
@@ -21,8 +21,6 @@
/**
* The exception that is thrown when a {@code CertPathBuilder} method fails.
- *
- * @since Android 1.0
*/
public class CertPathBuilderException extends GeneralSecurityException {
@@ -36,7 +34,6 @@
* the detail message for the exception
* @param cause
* why the building of the certification path failed.
- * @since Android 1.0
*/
public CertPathBuilderException(String msg, Throwable cause) {
super(msg, cause);
@@ -47,7 +44,6 @@
*
* @param cause
* why the building of the certification path failed.
- * @since Android 1.0
*/
public CertPathBuilderException(Throwable cause) {
super(cause);
@@ -59,7 +55,6 @@
*
* @param msg
* the detail message for the exception.
- * @since Android 1.0
*/
public CertPathBuilderException(String msg) {
super(msg);
@@ -67,9 +62,7 @@
/**
* Creates a new {@code CertPathBuilderException}.
- *
- * @since Android 1.0
*/
public CertPathBuilderException() {
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/cert/CertPathBuilderResult.java b/libcore/security/src/main/java/java/security/cert/CertPathBuilderResult.java
index e56c4a0..36d99a1 100644
--- a/libcore/security/src/main/java/java/security/cert/CertPathBuilderResult.java
+++ b/libcore/security/src/main/java/java/security/cert/CertPathBuilderResult.java
@@ -20,8 +20,6 @@
/**
* The interface for results generated by
* {@link CertPathBuilder#build(CertPathParameters)}.
- *
- * @since Android 1.0
*/
public interface CertPathBuilderResult extends Cloneable {
@@ -29,7 +27,6 @@
* Clones this {@code CertPathBuilderResult} instance.
*
* @return the copy of this instance.
- * @since Android 1.0
*/
public Object clone();
@@ -37,7 +34,6 @@
* Returns the built {@code CertPath} instance. Never returns {@code null}.
*
* @return the built certificate path instance.
- * @since Android 1.0
*/
public CertPath getCertPath();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/cert/CertPathBuilderSpi.java b/libcore/security/src/main/java/java/security/cert/CertPathBuilderSpi.java
index 952f387..80ee0ef 100644
--- a/libcore/security/src/main/java/java/security/cert/CertPathBuilderSpi.java
+++ b/libcore/security/src/main/java/java/security/cert/CertPathBuilderSpi.java
@@ -22,15 +22,11 @@
/**
* The <i>Service Provider Interface</i> (<b>SPI</b>) for the {@code
* CertPathBuilder} class to be implemented by security providers.
- *
- * @since Android 1.0
*/
public abstract class CertPathBuilderSpi {
/**
* Creates a new {@code CertPathBuilderSpi} instance.
- *
- * @since Android 1.0
*/
public CertPathBuilderSpi() {
}
@@ -46,7 +42,6 @@
* @throws InvalidAlgorithmParameterException
* if the specified parameters cannot be used to build the path
* with this builder.
- * @since Android 1.0
*/
public abstract CertPathBuilderResult engineBuild(CertPathParameters params)
throws CertPathBuilderException, InvalidAlgorithmParameterException;
diff --git a/libcore/security/src/main/java/java/security/cert/CertPathParameters.java b/libcore/security/src/main/java/java/security/cert/CertPathParameters.java
index c99826f..e2cee18 100644
--- a/libcore/security/src/main/java/java/security/cert/CertPathParameters.java
+++ b/libcore/security/src/main/java/java/security/cert/CertPathParameters.java
@@ -22,8 +22,6 @@
* <p>
* This interface is for grouping purposes of {@code CertPath} parameter
* implementations.
- * </p>
- * @since Android 1.0
*/
public interface CertPathParameters extends Cloneable {
@@ -31,7 +29,6 @@
* Clones this {@code CertPathParameters} instance.
*
* @return the cloned instance.
- * @since Android 1.0
*/
public Object clone();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/cert/CertPathValidator.java b/libcore/security/src/main/java/java/security/cert/CertPathValidator.java
index f95bd03..0d73280 100644
--- a/libcore/security/src/main/java/java/security/cert/CertPathValidator.java
+++ b/libcore/security/src/main/java/java/security/cert/CertPathValidator.java
@@ -32,8 +32,6 @@
* This class provides the functionality for validating certification paths
* (certificate chains) establishing a trust chain from a certificate to a trust
* anchor.
- *
- * @since Android 1.0
*/
public class CertPathValidator {
// Store CertPathValidator implementation service name
@@ -60,14 +58,13 @@
/**
* Creates a new {@code CertPathValidator} instance.
- *
+ *
* @param validatorSpi
* the implementation delegate.
* @param provider
* the security provider.
* @param algorithm
* the name of the algorithm.
- * @since Android 1.0
*/
protected CertPathValidator(CertPathValidatorSpi validatorSpi,
Provider provider, String algorithm) {
@@ -78,9 +75,8 @@
/**
* Returns the certification path algorithm name.
- *
+ *
* @return the certification path algorithm name.
- * @since Android 1.0
*/
public final String getAlgorithm() {
return algorithm;
@@ -88,9 +84,8 @@
/**
* Returns the security provider.
- *
+ *
* @return the provider.
- * @since Android 1.0
*/
public final Provider getProvider() {
return provider;
@@ -106,7 +101,6 @@
* if no installed provider provides the specified algorithm.
* @throws NullPointerException
* if algorithm is {@code null}.
- * @since Android 1.0
*/
public static CertPathValidator getInstance(String algorithm)
throws NoSuchAlgorithmException {
@@ -138,7 +132,6 @@
* if algorithm is {@code null}.
* @throws IllegalArgumentException
* if provider is {@code null} or empty.
- * @since Android 1.0
*/
public static CertPathValidator getInstance(String algorithm,
String provider) throws NoSuchAlgorithmException,
@@ -169,7 +162,6 @@
* if provider is {@code null}.
* @throws NullPointerException
* if algorithm is {@code null}.
- * @since Android 1.0
*/
public static CertPathValidator getInstance(String algorithm,
Provider provider) throws NoSuchAlgorithmException {
@@ -203,7 +195,6 @@
* if the specified algorithm parameters cannot be used with
* this algorithm.
* @see CertPathValidatorResult
- * @since Android 1.0
*/
public final CertPathValidatorResult validate(CertPath certPath,
CertPathParameters params) throws CertPathValidatorException,
@@ -214,11 +205,10 @@
/**
* Returns the default {@code CertPathValidator} type from the <i>Security
* Properties</i>.
- *
+ *
* @return the default {@code CertPathValidator} type from the <i>Security
* Properties</i>, or the string {@code "PKIX"} if it cannot be
* determined.
- * @since Android 1.0
*/
public static final String getDefaultType() {
String defaultType = AccessController
@@ -229,4 +219,4 @@
});
return (defaultType != null ? defaultType : DEFAULTPROPERTY);
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/cert/CertPathValidatorException.java b/libcore/security/src/main/java/java/security/cert/CertPathValidatorException.java
index 072785c..4d2b69f 100644
--- a/libcore/security/src/main/java/java/security/cert/CertPathValidatorException.java
+++ b/libcore/security/src/main/java/java/security/cert/CertPathValidatorException.java
@@ -28,9 +28,6 @@
* A {@code CertPathValidatorException} may optionally include the certification
* path instance that failed the validation and the index of the failed
* certificate.
- * </p>
- *
- * @since Android 1.0
*/
public class CertPathValidatorException extends GeneralSecurityException {
@@ -65,7 +62,6 @@
* @throws IndexOutOfBoundsException
* if {@code certPath} is not {@code null} and index is not
* referencing an certificate in the certification path.
- * @since Android 1.0
*/
public CertPathValidatorException(String msg, Throwable cause,
CertPath certPath, int index) {
@@ -91,7 +87,6 @@
* the detail message for this exception.
* @param cause
* the cause why the path could not be validated.
- * @since Android 1.0
*/
public CertPathValidatorException(String msg, Throwable cause) {
super(msg, cause);
@@ -103,7 +98,6 @@
*
* @param cause
* the cause why the path could not be validated.
- * @since Android 1.0
*/
public CertPathValidatorException(Throwable cause) {
super(cause);
@@ -115,7 +109,6 @@
*
* @param msg
* the detail message for this exception.
- * @since Android 1.0
*/
public CertPathValidatorException(String msg) {
super(msg);
@@ -123,8 +116,6 @@
/**
* Creates a new {@code CertPathValidatorException}.
- *
- * @since Android 1.0
*/
public CertPathValidatorException() {
}
@@ -134,7 +125,6 @@
*
* @return the certification path that failed validation, or {@code null} if
* none was specified.
- * @since Android 1.0
*/
public CertPath getCertPath() {
return certPath;
@@ -145,9 +135,8 @@
*
* @return the index of the failed certificate in the certification path, or
* {@code -1} if none was specified.
- * @since Android 1.0
*/
public int getIndex() {
return index;
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/cert/CertPathValidatorResult.java b/libcore/security/src/main/java/java/security/cert/CertPathValidatorResult.java
index 42540e4..7fab21a 100644
--- a/libcore/security/src/main/java/java/security/cert/CertPathValidatorResult.java
+++ b/libcore/security/src/main/java/java/security/cert/CertPathValidatorResult.java
@@ -21,8 +21,6 @@
* The interface specification for certification path validation results.
* <p>
* This interface is for grouping purposes of validation result implementations.
- * </p>
- * @since Android 1.0
*/
public interface CertPathValidatorResult extends Cloneable {
@@ -30,7 +28,6 @@
* Clones this {@code CertPathValidatorResult} instance.
*
* @return the cloned instance.
- * @since Android 1.0
*/
public Object clone();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/cert/CertPathValidatorSpi.java b/libcore/security/src/main/java/java/security/cert/CertPathValidatorSpi.java
index 5573679..e14e8dd 100644
--- a/libcore/security/src/main/java/java/security/cert/CertPathValidatorSpi.java
+++ b/libcore/security/src/main/java/java/security/cert/CertPathValidatorSpi.java
@@ -22,15 +22,11 @@
/**
* The <i>Service Provider Interface</i> (<b>SPI</b>) for the {@code
* CertPathValidator} class to be implemented by security providers.
- *
- * @since Android 1.0
*/
public abstract class CertPathValidatorSpi {
/**
* Creates a new {@code CertPathValidatorSpi} instance.
- *
- * @since Android 1.0
*/
public CertPathValidatorSpi() {
}
@@ -38,7 +34,7 @@
/**
* Validates the {@code CertPath} with the algorithm of this {@code
* CertPathValidator} using the specified algorithm parameters.
- *
+ *
* @param certPath
* the certification path to be validated.
* @param params
@@ -51,10 +47,9 @@
* @throws InvalidAlgorithmParameterException
* if the specified algorithm parameters cannot be used with
* this algorithm.
- * @since Android 1.0
*/
public abstract CertPathValidatorResult engineValidate(CertPath certPath,
CertPathParameters params) throws CertPathValidatorException,
InvalidAlgorithmParameterException;
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/cert/CertSelector.java b/libcore/security/src/main/java/java/security/cert/CertSelector.java
index 0316ad3..c490b22 100644
--- a/libcore/security/src/main/java/java/security/cert/CertSelector.java
+++ b/libcore/security/src/main/java/java/security/cert/CertSelector.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
package java.security.cert;
/**
@@ -28,11 +23,9 @@
* <p>
* The implementations of this interface are typically used to define the
* criteria for selecting {@code Certificate}s from a {@code CertStore}.
- * </p>
*
* @see CertStore
* @see Certificate
- * @since Android 1.0
*/
public interface CertSelector extends Cloneable {
@@ -40,7 +33,6 @@
* Clones this {@code CertSelector} instance.
*
* @return the cloned instance.
- * @since Android 1.0
*/
public Object clone();
@@ -52,7 +44,6 @@
* the certificate to be evaluated.
* @return {@code true} if the certificate matches the criteria, {@code
* false} otherwise.
- * @since Android 1.0
*/
public boolean match(Certificate cert);
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/cert/CertStore.java b/libcore/security/src/main/java/java/security/cert/CertStore.java
index a5c8260..d0b7600 100644
--- a/libcore/security/src/main/java/java/security/cert/CertStore.java
+++ b/libcore/security/src/main/java/java/security/cert/CertStore.java
@@ -33,8 +33,6 @@
* This class provides the functionality to retrieve {@code Certificate}s and
* {@code CRL}s from a read-only repository. This repository may be very large
* and may store trusted as well as untrusted certificates.
- *
- * @since Android 1.0
*/
public class CertStore {
@@ -65,7 +63,7 @@
/**
* Creates a new {@code CertStore} instance.
- *
+ *
* @param storeSpi
* the implementation delegate.
* @param provider
@@ -74,7 +72,6 @@
* the certificate store type.
* @param params
* the certificate store parameters (may be {@code null}.
- * @since Android 1.0
*/
protected CertStore(CertStoreSpi storeSpi, Provider provider, String type,
CertStoreParameters params) {
@@ -101,7 +98,6 @@
* certificate store instance.
* @throws NullPointerException
* if the {@code type} is {@code null}.
- * @since Android 1.0
*/
public static CertStore getInstance(String type, CertStoreParameters params)
throws InvalidAlgorithmParameterException, NoSuchAlgorithmException {
@@ -147,7 +143,6 @@
* if provider is null of empty.
* @throws NullPointerException
* if {@code type} is {@code null}.
- * @since Android 1.0
*/
public static CertStore getInstance(String type,
CertStoreParameters params, String provider)
@@ -183,7 +178,6 @@
* if provider is {@code null}.
* @throws NullPointerException
* if {@code type} is {@code null}.
- * @since Android 1.0
*/
public static CertStore getInstance(String type,
CertStoreParameters params, Provider provider)
@@ -212,9 +206,8 @@
/**
* Returns the certificate store type.
- *
+ *
* @return the certificate store type.
- * @since Android 1.0
*/
public final String getType() {
return type;
@@ -222,9 +215,8 @@
/**
* Returns the security provider.
- *
+ *
* @return the security provider.
- * @since Android 1.0
*/
public final Provider getProvider() {
return provider;
@@ -233,10 +225,9 @@
/**
* Returns a copy of the certificate store parameters that were used to
* initialize this instance.
- *
+ *
* @return a copy of the certificate store parameters or {@code null} if
* none were specified.
- * @since Android 1.0
*/
public final CertStoreParameters getCertStoreParameters() {
if (certStoreParams == null) {
@@ -249,7 +240,7 @@
/**
* Returns the list of {@code Certificate}s for the specified {@code
* CertSelector} from this certificate store.
- *
+ *
* @param selector
* the selector containing the criteria to search for
* certificates in this certificate store.
@@ -257,7 +248,6 @@
* specified selector.
* @throws CertStoreException
* if error(s) occur.
- * @since Android 1.0
*/
public final Collection<? extends Certificate> getCertificates(CertSelector selector)
throws CertStoreException {
@@ -267,7 +257,7 @@
/**
* Returns the list of {@code CRL}s for the specified {@code CRLSelector}
* from this certificate store.
- *
+ *
* @param selector
* the selector containing the criteria to search for certificate
* revocation lists in this store.
@@ -275,7 +265,6 @@
* selector
* @throws CertStoreException
* if error(s) occur.
- * @since Android 1.0
*/
public final Collection<? extends CRL> getCRLs(CRLSelector selector)
throws CertStoreException {
@@ -285,12 +274,11 @@
/**
* Returns the default {@code CertStore} type from the <i>Security
* Properties</i>.
- *
+ *
* @return the default {@code CertStore} type from the <i>Security
* Properties</i>, or the string {@code "LDAP"} if it cannot be
* determined.
- * @since Android 1.0
- */
+ */
public static final String getDefaultType() {
String defaultType = AccessController
.doPrivileged(new java.security.PrivilegedAction<String>() {
diff --git a/libcore/security/src/main/java/java/security/cert/CertStoreException.java b/libcore/security/src/main/java/java/security/cert/CertStoreException.java
index 8351605..7f356b2 100644
--- a/libcore/security/src/main/java/java/security/cert/CertStoreException.java
+++ b/libcore/security/src/main/java/java/security/cert/CertStoreException.java
@@ -21,8 +21,6 @@
/**
* The exception that is thrown when an access to a {@code CertStore} fails.
- *
- * @since Android 1.0
*/
public class CertStoreException extends GeneralSecurityException {
@@ -36,7 +34,6 @@
* the detail message for this exception.
* @param cause
* the cause why the access to the certificate store failed.
- * @since Android 1.0
*/
public CertStoreException(String msg, Throwable cause) {
super(msg, cause);
@@ -47,7 +44,6 @@
*
* @param cause
* the cause why the access to the certificate store failed.
- * @since Android 1.0
*/
public CertStoreException(Throwable cause) {
super(cause);
@@ -58,7 +54,6 @@
*
* @param msg
* the detail message for this exception.
- * @since Android 1.0
*/
public CertStoreException(String msg) {
super(msg);
@@ -66,9 +61,7 @@
/**
* Creates a new {@code CertStoreException}.
- *
- * @since Android 1.0
*/
public CertStoreException() {
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/cert/CertStoreParameters.java b/libcore/security/src/main/java/java/security/cert/CertStoreParameters.java
index 566b2e2..06a1976 100644
--- a/libcore/security/src/main/java/java/security/cert/CertStoreParameters.java
+++ b/libcore/security/src/main/java/java/security/cert/CertStoreParameters.java
@@ -20,8 +20,6 @@
/**
* The marker interface specifying the parameters used to initialize a {@code
* CertStore} instance.
- *
- * @since Android 1.0
*/
public interface CertStoreParameters extends Cloneable {
@@ -29,7 +27,6 @@
* Clones this {@code CertStoreParameters} instance.
*
* @return the cloned instance.
- * @since Android 1.0
*/
public Object clone();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/cert/CertStoreSpi.java b/libcore/security/src/main/java/java/security/cert/CertStoreSpi.java
index be680a7..cb38a31 100644
--- a/libcore/security/src/main/java/java/security/cert/CertStoreSpi.java
+++ b/libcore/security/src/main/java/java/security/cert/CertStoreSpi.java
@@ -23,8 +23,6 @@
/**
* The <i>Service Provider Interface</i> (<b>SPI</b>) definition for the {@code
* CertStore} class to be implemented by security providers.
- *
- * @since Android 1.0
*/
public abstract class CertStoreSpi {
@@ -36,7 +34,6 @@
* @throws InvalidAlgorithmParameterException
* if the specified initialization parameters cannot be used to
* initialize this instance.
- * @since Android 1.0
*/
public CertStoreSpi(CertStoreParameters params)
throws InvalidAlgorithmParameterException {
@@ -53,7 +50,6 @@
* specified selector.
* @throws CertStoreException
* if error(s) occur.
- * @since Android 1.0
*/
public abstract Collection<? extends Certificate> engineGetCertificates(CertSelector selector)
throws CertStoreException;
@@ -69,7 +65,6 @@
* selector
* @throws CertStoreException
* if error(s) occur.
- * @since Android 1.0
*/
public abstract Collection<? extends CRL> engineGetCRLs(CRLSelector selector)
throws CertStoreException;
diff --git a/libcore/security/src/main/java/java/security/cert/Certificate.java b/libcore/security/src/main/java/java/security/cert/Certificate.java
index 0543329..22cbe9c 100644
--- a/libcore/security/src/main/java/java/security/cert/Certificate.java
+++ b/libcore/security/src/main/java/java/security/cert/Certificate.java
@@ -35,8 +35,6 @@
* Abstract class to represent identity certificates. It represents a way to
* verify the binding of a Principal and its public key. Examples are X.509,
* PGP, and SDSI.
- *
- * @since Android 1.0
*/
public abstract class Certificate implements Serializable {
@@ -47,10 +45,9 @@
/**
* Creates a new {@code Certificate} with the specified type.
- *
+ *
* @param type
* the certificate type.
- * @since Android 1.0
*/
protected Certificate(String type) {
this.type = type;
@@ -58,9 +55,8 @@
/**
* Returns the certificate type.
- *
+ *
* @return the certificate type.
- * @since Android 1.0
*/
public final String getType() {
return type;
@@ -71,13 +67,12 @@
* represent the <em>same</em> object using a class specific comparison. The
* implementation in Object returns {@code true} only if the argument is the
* exact same object as the callee (==).
- *
+ *
* @param other
* the object to compare with this object.
* @return {@code true} if the object is the same as this object, {@code
* false} if it is different from this object.
* @see #hashCode
- * @since Android 1.0
*/
public boolean equals(Object other) {
// obj equal to itself
@@ -100,10 +95,9 @@
* Returns an integer hash code for the certificate. Any two objects which
* return {@code true} when passed to {@code equals} must return the same
* value for this method.
- *
+ *
* @return the certificate's hash
* @see #equals
- * @since Android 1.0
*/
public int hashCode() {
try {
@@ -120,17 +114,16 @@
/**
* Returns the encoded representation for this certificate.
- *
+ *
* @return the encoded representation for this certificate.
* @throws CertificateEncodingException
* if the encoding fails.
- * @since Android 1.0
*/
public abstract byte[] getEncoded() throws CertificateEncodingException;
/**
* Verifies that this certificate was signed with the given public key.
- *
+ *
* @param key
* PublicKey public key for which verification should be
* performed.
@@ -144,7 +137,6 @@
* if there is no default provider.
* @throws SignatureException
* if signature errors are detected.
- * @since Android 1.0
*/
public abstract void verify(PublicKey key)
throws CertificateException,
@@ -156,7 +148,7 @@
/**
* Verifies that this certificate was signed with the given public key. It
* Uses the signature algorithm given by the provider.
- *
+ *
* @param key
* PublicKey public key for which verification should be
* performed.
@@ -172,7 +164,6 @@
* if the specified provider does not exists.
* @exception SignatureException
* if signature errors are detected.
- * @since Android 1.0
*/
public abstract void verify(PublicKey key, String sigProvider)
throws CertificateException,
@@ -184,27 +175,24 @@
/**
* Returns a string containing a concise, human-readable description of the
* certificate.
- *
+ *
* @return a printable representation for the certificate.
- * @since Android 1.0
*/
public abstract String toString();
/**
* Returns the public key corresponding to this certificate.
- *
+ *
* @return the public key corresponding to this certificate.
- * @since Android 1.0
*/
public abstract PublicKey getPublicKey();
/**
* Returns an alternate object to be serialized.
- *
+ *
* @return the object to serialize.
* @throws ObjectStreamException
* if the creation of the alternate object fails.
- * @since Android 1.0
*/
protected Object writeReplace() throws ObjectStreamException {
try {
@@ -217,9 +205,7 @@
/**
* The alternate {@code Serializable} class to be used for serialization and
- * deserialization of {@code Certificate} objects.
- *
- * @since Android 1.0
+ * deserialization of {@code Certificate} objects.
*/
protected static class CertificateRep implements Serializable {
@@ -239,12 +225,11 @@
/**
* Creates a new {@code CertificateRep} instance with the specified
* certificate type and encoded data.
- *
+ *
* @param type
* the certificate type.
* @param data
* the encoded data.
- * @since Android 1.0
*/
protected CertificateRep(String type, byte[] data) {
this.type = type;
@@ -254,11 +239,10 @@
/**
* Deserializes a {@code Certificate} from a serialized {@code
* CertificateRep} object.
- *
+ *
* @return the deserialized {@code Certificate}.
* @throws ObjectStreamException
* if deserialization fails.
- * @since Android 1.0
*/
protected Object readResolve() throws ObjectStreamException {
try {
diff --git a/libcore/security/src/main/java/java/security/cert/CertificateEncodingException.java b/libcore/security/src/main/java/java/security/cert/CertificateEncodingException.java
index 188d084..c5532b9 100644
--- a/libcore/security/src/main/java/java/security/cert/CertificateEncodingException.java
+++ b/libcore/security/src/main/java/java/security/cert/CertificateEncodingException.java
@@ -20,8 +20,6 @@
/**
* The exception that is thrown when an error occurs while a {@code Certificate}
* is being encoded.
- *
- * @since Android 1.0
*/
public class CertificateEncodingException extends CertificateException {
@@ -33,7 +31,6 @@
*
* @param msg
* The detail message for the exception.
- * @since Android 1.0
*/
public CertificateEncodingException(String msg) {
super(msg);
@@ -41,8 +38,6 @@
/**
* Creates a new {@code CertificateEncodingException}.
- *
- * @since Android 1.0
*/
public CertificateEncodingException() {
}
@@ -55,7 +50,6 @@
* the detail message for the exception.
* @param cause
* the cause.
- * @since Android 1.0
*/
public CertificateEncodingException(String message, Throwable cause) {
super(message, cause);
@@ -67,7 +61,6 @@
*
* @param cause
* the cause.
- * @since Android 1.0
*/
public CertificateEncodingException(Throwable cause) {
super(cause);
diff --git a/libcore/security/src/main/java/java/security/cert/CertificateException.java b/libcore/security/src/main/java/java/security/cert/CertificateException.java
index 674d617..8b1c4d3 100644
--- a/libcore/security/src/main/java/java/security/cert/CertificateException.java
+++ b/libcore/security/src/main/java/java/security/cert/CertificateException.java
@@ -21,8 +21,6 @@
/**
* The base class for all {@code Certificate} related exceptions.
- *
- * @since Android 1.0
*/
public class CertificateException extends GeneralSecurityException {
@@ -33,7 +31,6 @@
*
* @param msg
* the detail message for the exception.
- * @since Android 1.0
*/
public CertificateException(String msg) {
super(msg);
@@ -41,8 +38,6 @@
/**
* Creates a new {@code CertificateException}.
- *
- * @since Android 1.0
*/
public CertificateException() {
}
@@ -55,7 +50,6 @@
* the detail message for the exception.
* @param cause
* the cause.
- * @since Android 1.0
*/
public CertificateException(String message, Throwable cause) {
super(message, cause);
@@ -66,7 +60,6 @@
*
* @param cause
* the cause
- * @since Android 1.0
*/
public CertificateException(Throwable cause) {
super(cause);
diff --git a/libcore/security/src/main/java/java/security/cert/CertificateExpiredException.java b/libcore/security/src/main/java/java/security/cert/CertificateExpiredException.java
index fe3fc1f..e15bf98 100644
--- a/libcore/security/src/main/java/java/security/cert/CertificateExpiredException.java
+++ b/libcore/security/src/main/java/java/security/cert/CertificateExpiredException.java
@@ -19,8 +19,6 @@
/**
* The exception that is thrown when a {@code Certificate} has expired.
- *
- * @since Android 1.0
*/
public class CertificateExpiredException extends CertificateException {
@@ -32,7 +30,6 @@
*
* @param msg
* the detail message for this exception
- * @since Android 1.0
*/
public CertificateExpiredException(String msg) {
super(msg);
@@ -40,8 +37,6 @@
/**
* Creates a new {@code CertificateExpiredException}.
- *
- * @since Android 1.0
*/
public CertificateExpiredException() {
}
diff --git a/libcore/security/src/main/java/java/security/cert/CertificateFactory.java b/libcore/security/src/main/java/java/security/cert/CertificateFactory.java
index b4213d4..cb2636a 100644
--- a/libcore/security/src/main/java/java/security/cert/CertificateFactory.java
+++ b/libcore/security/src/main/java/java/security/cert/CertificateFactory.java
@@ -36,9 +36,6 @@
* <p>
* It defines methods for parsing certificate chains (certificate paths) and
* <i>Certificate Revocation Lists</i> (CRLs).
- * </p>
- *
- * @since Android 1.0
*/
public class CertificateFactory {
@@ -59,14 +56,13 @@
/**
* Creates a new {@code CertificateFactory} instance.
- *
+ *
* @param certFacSpi
* the implementation delegate.
* @param provider
* the associated provider.
* @param type
* the certificate type.
- * @since Android 1.0
*/
protected CertificateFactory(CertificateFactorySpi certFacSpi,
Provider provider, String type) {
@@ -87,7 +83,6 @@
* installed provider.
* @throws NullPointerException
* if {@code type} is {@code null}.
- * @since Android 1.0
*/
public static final CertificateFactory getInstance(String type)
throws CertificateException {
@@ -124,7 +119,6 @@
* if the specified provider name is {@code null} or empty.
* @throws NullPointerException
* it {@code type} is {@code null}.
- * @since Android 1.0
*/
public static final CertificateFactory getInstance(String type,
String provider) throws CertificateException,
@@ -156,7 +150,6 @@
* if the specified provider is {@code null}.
* @throws NullPointerException
* is {@code type} is {@code null}.
- * @since Android 1.0
*/
public static final CertificateFactory getInstance(String type,
Provider provider) throws CertificateException {
@@ -182,7 +175,6 @@
* the certificate.
*
* @return the provider of this certificate factory.
- * @since Android 1.0
*/
public final Provider getProvider() {
return provider;
@@ -192,7 +184,6 @@
* Returns the Certificate type.
*
* @return type of certificate being used.
- * @since Android 1.0
*/
public final String getType() {
return type;
@@ -208,7 +199,6 @@
* @return an initialized Certificate.
* @throws CertificateException
* if parsing problems are detected.
- * @since Android 1.0
*/
public final Certificate generateCertificate(InputStream inStream)
throws CertificateException {
@@ -221,7 +211,6 @@
*
* @return an iterator over supported {@link CertPath} encodings (as
* Strings).
- * @since Android 1.0
*/
public final Iterator<String> getCertPathEncodings() {
return spiImpl.engineGetCertPathEncodings();
@@ -236,7 +225,6 @@
* @return a {@code CertPath} initialized from the provided data.
* @throws CertificateException
* if parsing problems are detected.
- * @since Android 1.0
*/
public final CertPath generateCertPath(InputStream inStream)
throws CertificateException {
@@ -261,7 +249,6 @@
* if parsing problems are detected.
* @throws UnsupportedOperationException
* if the provider does not implement this method.
- * @since Android 1.0
*/
public final CertPath generateCertPath(InputStream inStream, String encoding)
throws CertificateException {
@@ -280,7 +267,6 @@
* if parsing problems are detected.
* @throws UnsupportedOperationException
* if the provider does not implement this method.
- * @since Android 1.0
*/
public final CertPath generateCertPath(List<? extends Certificate> certificates)
throws CertificateException {
@@ -297,7 +283,6 @@
* @return an initialized collection of certificates.
* @throws CertificateException
* if parsing problems are detected.
- * @since Android 1.0
*/
public final Collection<? extends Certificate> generateCertificates(InputStream inStream)
throws CertificateException {
@@ -313,7 +298,6 @@
* @return an initialized CRL.
* @exception CRLException
* if parsing problems are detected.
- * @since Android 1.0
*/
public final CRL generateCRL(InputStream inStream) throws CRLException {
return spiImpl.engineGenerateCRL(inStream);
@@ -328,7 +312,6 @@
* @return an initialized collection of CRLs.
* @exception CRLException
* if parsing problems are detected.
- * @since Android 1.0
*/
public final Collection<? extends CRL> generateCRLs(InputStream inStream)
throws CRLException {
diff --git a/libcore/security/src/main/java/java/security/cert/CertificateFactorySpi.java b/libcore/security/src/main/java/java/security/cert/CertificateFactorySpi.java
index ed6ffed..d9f2044 100644
--- a/libcore/security/src/main/java/java/security/cert/CertificateFactorySpi.java
+++ b/libcore/security/src/main/java/java/security/cert/CertificateFactorySpi.java
@@ -28,16 +28,12 @@
* This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) for the
* {@code CertificateFactory} class. This SPI must be implemented for each
* certificate type a security provider wishes to support.
- *
- * @since Android 1.0
*/
public abstract class CertificateFactorySpi {
/**
* Constructs a new instance of this class.
- *
- * @since Android 1.0
*/
public CertificateFactorySpi() {
}
@@ -52,7 +48,6 @@
* @return an initialized certificate.
* @exception CertificateException
* if parsing problems are detected.
- * @since Android 1.0
*/
public abstract Certificate engineGenerateCertificate(InputStream inStream)
throws CertificateException;
@@ -66,7 +61,6 @@
* @return a collection of certificates.
* @exception CertificateException
* if parsing problems are detected.
- * @since Android 1.0
*/
public abstract Collection<? extends Certificate>
engineGenerateCertificates(InputStream inStream) throws CertificateException;
@@ -80,7 +74,6 @@
* @return an CRL instance.
* @exception CRLException
* if parsing problems are detected.
- * @since Android 1.0
*/
public abstract CRL engineGenerateCRL(InputStream inStream)
throws CRLException;
@@ -94,7 +87,6 @@
* @return a collection of CRLs.
* @exception CRLException
* if parsing problems are detected.
- * @since Android 1.0
*/
public abstract Collection<? extends CRL>
engineGenerateCRLs(InputStream inStream) throws CRLException;
@@ -108,7 +100,6 @@
* @return a {@code CertPath} initialized from the provided data.
* @throws CertificateException
* if parsing problems are detected.
- * @since Android 1.0
*/
public CertPath engineGenerateCertPath(InputStream inStream)
throws CertificateException {
@@ -130,7 +121,6 @@
* if parsing problems are detected.
* @throws UnsupportedOperationException
* if the provider does not implement this method.
- * @since Android 1.0
*/
public CertPath engineGenerateCertPath(InputStream inStream, String encoding)
throws CertificateException {
@@ -150,7 +140,6 @@
* if parsing problems are detected.
* @throws UnsupportedOperationException
* if the provider does not implement this method.
- * @since Android 1.0
*/
public CertPath engineGenerateCertPath(List<? extends Certificate> certificates)
throws CertificateException {
@@ -164,7 +153,6 @@
*
* @return an iterator over supported {@code CertPath} encodings (as
* Strings).
- * @since Android 1.0
*/
public Iterator<String> engineGetCertPathEncodings() {
throw new UnsupportedOperationException(
diff --git a/libcore/security/src/main/java/java/security/cert/CertificateNotYetValidException.java b/libcore/security/src/main/java/java/security/cert/CertificateNotYetValidException.java
index 221b22a..dd26bf8 100644
--- a/libcore/security/src/main/java/java/security/cert/CertificateNotYetValidException.java
+++ b/libcore/security/src/main/java/java/security/cert/CertificateNotYetValidException.java
@@ -20,8 +20,6 @@
/**
* The exception that is thrown when a {@code Certificate} is not yet valid or
* will not yet be valid on a specified date.
- *
- * @since Android 1.0
*/
public class CertificateNotYetValidException extends CertificateException {
@@ -33,7 +31,6 @@
*
* @param msg
* the detail message for the exception.
- * @since Android 1.0
*/
public CertificateNotYetValidException(String msg) {
super(msg);
@@ -41,8 +38,6 @@
/**
* Creates a new {@code CertificateNotYetValidException}.
- *
- * @since Android 1.0
*/
public CertificateNotYetValidException() {
}
diff --git a/libcore/security/src/main/java/java/security/cert/CertificateParsingException.java b/libcore/security/src/main/java/java/security/cert/CertificateParsingException.java
index 2c75d20..4efd159 100644
--- a/libcore/security/src/main/java/java/security/cert/CertificateParsingException.java
+++ b/libcore/security/src/main/java/java/security/cert/CertificateParsingException.java
@@ -19,8 +19,6 @@
/**
* The exception that is thrown when a {@code Certificate} can not be parsed.
- *
- * @since Android 1.0
*/
public class CertificateParsingException extends CertificateException {
@@ -29,10 +27,9 @@
/**
* Creates a new {@code CertificateParsingException} with the specified
* message.
- *
+ *
* @param msg
* the detail message for the exception.
- * @since Android 1.0
*/
public CertificateParsingException(String msg) {
super(msg);
@@ -40,8 +37,6 @@
/**
* Creates a new {@code CertificateParsingException}.
- *
- * @since Android 1.0
*/
public CertificateParsingException() {
}
@@ -49,12 +44,11 @@
/**
* Creates a new {@code CertificateParsingException} with the specified
* message and cause.
- *
+ *
* @param message
* the detail message for the exception.
* @param cause
* the exception's source.
- * @since Android 1.0
*/
public CertificateParsingException(String message, Throwable cause) {
super(message, cause);
@@ -63,10 +57,9 @@
/**
* Creates a new {@code CertificateParsingException} with the specified
* cause.
- *
+ *
* @param cause
* the exception's source.
- * @since Android 1.0
*/
public CertificateParsingException(Throwable cause) {
super(cause);
diff --git a/libcore/security/src/main/java/java/security/cert/CollectionCertStoreParameters.java b/libcore/security/src/main/java/java/security/cert/CollectionCertStoreParameters.java
index 23d8884..3c2fe1c 100644
--- a/libcore/security/src/main/java/java/security/cert/CollectionCertStoreParameters.java
+++ b/libcore/security/src/main/java/java/security/cert/CollectionCertStoreParameters.java
@@ -24,13 +24,9 @@
* The parameters to initialize a <i>Collection</i> type {@code CertStore} instance.
* <p>
* It is used to specify the {@code Collection} where the {@code CertStore} will
- * retrieve the certificates and CRLs from.
- * </p>
- *
- * @since Android 1.0
+ * retrieve the certificates and CRLs from.
*/
public class CollectionCertStoreParameters implements CertStoreParameters {
- // BEGIN android-changed
// Default empty and immutable collection.
// Used if <code>CollectionCertStoreParameters</code>instance
// created by the no arg constructor
@@ -38,14 +34,11 @@
// A <code>Collection</code> of <code>Certificate</code>s
// and <code>CRL</code>s
private final Collection<?> collection;
- // END android-changed
/**
* Creates a new {@code CollectionCertStoreParameters} without a collection.
* <p>
* The default collection is an empty and unmodifiable {@code Collection}.
- * </p>
- * @since Android 1.0
*/
public CollectionCertStoreParameters() {
this.collection = defaultCollection;
@@ -57,14 +50,12 @@
* <p>
* The specified collection is not copied and therefore may be modified at
* any time.
- * </p>
- *
+ *
* @param collection
* the collection where the {@code Certificate}s and {@code CRL}s
* will be retrieved from.
* @throws NullPointerException
* if {@code collection is null}.
- * @since Android 1.0
*/
public CollectionCertStoreParameters(Collection<?> collection) {
this.collection = collection;
@@ -76,21 +67,23 @@
/**
* Clones this {@code CollectionCertStoreParameters} instance, but not the
* underlying collection.
- *
+ *
* @return the cloned instance.
- * @since Android 1.0
*/
public Object clone() {
- return new CollectionCertStoreParameters(collection);
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ return null;
+ }
}
/**
* Returns the collection where the {@code Certificate}s and {@code CRL}s
* are retrieved from.
- *
+ *
* @return the collection where the {@code Certificate}s and {@code CRL}s
* will be retrieved from.
- * @since Android 1.0
*/
public Collection<?> getCollection() {
return collection;
@@ -98,13 +91,12 @@
/**
* Returns the string representation of this instance.
- *
+ *
* @return the string representation of this instance.
- * @since Android 1.0
*/
public String toString() {
- StringBuffer sb =
- new StringBuffer("CollectionCertStoreParameters: [\ncollection: "); //$NON-NLS-1$
+ StringBuilder sb =
+ new StringBuilder("CollectionCertStoreParameters: [\ncollection: "); //$NON-NLS-1$
sb.append(getCollection().toString());
sb.append("\n]"); //$NON-NLS-1$
return sb.toString();
diff --git a/libcore/security/src/main/java/java/security/cert/LDAPCertStoreParameters.java b/libcore/security/src/main/java/java/security/cert/LDAPCertStoreParameters.java
index 9145848..1d6542f 100644
--- a/libcore/security/src/main/java/java/security/cert/LDAPCertStoreParameters.java
+++ b/libcore/security/src/main/java/java/security/cert/LDAPCertStoreParameters.java
@@ -19,8 +19,6 @@
/**
* The parameters to initialize a LDAP {@code CertStore} instance.
- *
- * @since Android 1.0
*/
public class LDAPCertStoreParameters implements CertStoreParameters {
// Default LDAP server name
@@ -36,14 +34,13 @@
/**
* Creates a new {@code LDAPCertStoreParameters} instance with the specified
* server name and port.
- *
+ *
* @param serverName
* the LDAP server name.
* @param port
* the port.
* @throws NullPointerException
* is {@code serverName} is {@code null}.
- * @since Android 1.0
*/
public LDAPCertStoreParameters(String serverName, int port) {
this.port = port;
@@ -58,9 +55,6 @@
* parameters.
* <p>
* The default parameters are server name "localhost" and port 389.
- * </p>
- *
- * @since Android 1.0
*/
public LDAPCertStoreParameters() {
this.serverName = DEFAULT_LDAP_SERVER_NAME;
@@ -70,12 +64,11 @@
/**
* Creates a new {@code LDAPCertStoreParameters} instance with the specified
* server name and default port 389.
- *
+ *
* @param serverName
* the LDAP server name.
* @throws NullPointerException
* if {@code serverName} is {@code null}.
- * @since Android 1.0
*/
public LDAPCertStoreParameters(String serverName) {
this.port = DEFAULT_LDAP_PORT;
@@ -87,19 +80,21 @@
/**
* Clones this {@code LDAPCertStoreParameters} instance.
- *
+ *
* @return the cloned instance.
- * @since Android 1.0
*/
public Object clone() {
- return new LDAPCertStoreParameters(serverName, port);
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ return null;
+ }
}
/**
* Returns the LDAP server port.
- *
+ *
* @return the LDAP server port.
- * @since Android 1.0
*/
public int getPort() {
return port;
@@ -107,9 +102,8 @@
/**
* Returns the LDAP server name.
- *
+ *
* @return the LDAP server name.
- * @since Android 1.0
*/
public String getServerName() {
return serverName;
@@ -118,14 +112,13 @@
/**
* Returns the string representation of this {@code LDAPCertStoreParameters}
* instance.
- *
+ *
* @return the string representation of this {@code LDAPCertStoreParameters}
* instance.
- * @since Android 1.0
*/
public String toString() {
- StringBuffer sb =
- new StringBuffer("LDAPCertStoreParameters: [\n serverName: "); //$NON-NLS-1$
+ StringBuilder sb =
+ new StringBuilder("LDAPCertStoreParameters: [\n serverName: "); //$NON-NLS-1$
sb.append(getServerName());
sb.append("\n port: "); //$NON-NLS-1$
sb.append(getPort());
diff --git a/libcore/security/src/main/java/java/security/cert/PKIXBuilderParameters.java b/libcore/security/src/main/java/java/security/cert/PKIXBuilderParameters.java
index a047a80..1a75063 100644
--- a/libcore/security/src/main/java/java/security/cert/PKIXBuilderParameters.java
+++ b/libcore/security/src/main/java/java/security/cert/PKIXBuilderParameters.java
@@ -32,11 +32,9 @@
* <p>
* The parameters must be created with <i>trusted</i> certificate authorities
* and constraints for the target certificates.
- * </p>
- *
+ *
* @see CertPathBuilder
* @see CertPathParameters
- * @since Android 1.0
*/
public class PKIXBuilderParameters extends PKIXParameters {
// Maximum certificate path length (5 by default)
@@ -55,7 +53,6 @@
* @throws ClassCastException
* if one of the items in {@code trustAnchors} is not an
* instance of {@code java.security.cert.TrustAnchor}.
- * @since Android 1.0
*/
public PKIXBuilderParameters(Set<TrustAnchor> trustAnchors,
CertSelector targetConstraints)
@@ -77,7 +74,6 @@
* @throws InvalidAlgorithmParameterException
* if {@code keyStore} does not contained any trusted
* certificate entry.
- * @since Android 1.0
*/
public PKIXBuilderParameters(KeyStore keyStore,
CertSelector targetConstraints)
@@ -92,11 +88,9 @@
* <p>
* This is the maximum number of non-self-signed certificates in a
* certification path.
- * </p>
- *
+ *
* @return the maximum length of a certification path, or {@code -1} if it
* is unlimited.
- * @since Android 1.0
*/
public int getMaxPathLength() {
return maxPathLength;
@@ -107,13 +101,11 @@
* <p>
* This is the maximum number of non-self-signed certificates in a
* certification path.
- * </p>
*
* @param maxPathLength
* the maximum length of a certification path.
* @throws InvalidParameterException
* if {@code maxPathLength} is less than {@code -1}.
- * @since Android 1.0
*/
public void setMaxPathLength(int maxPathLength) {
if (maxPathLength < -1) {
@@ -129,10 +121,9 @@
*
* @return a string representation of this {@code PKIXBuilderParameters}
* instance.
- * @since Android 1.0
*/
public String toString() {
- StringBuffer sb = new StringBuffer("[\n"); //$NON-NLS-1$
+ StringBuilder sb = new StringBuilder("[\n"); //$NON-NLS-1$
sb.append(super.toString());
sb.append(" Max Path Length: "); //$NON-NLS-1$
sb.append(maxPathLength);
diff --git a/libcore/security/src/main/java/java/security/cert/PKIXCertPathBuilderResult.java b/libcore/security/src/main/java/java/security/cert/PKIXCertPathBuilderResult.java
index 6064194..5a9fb2d 100644
--- a/libcore/security/src/main/java/java/security/cert/PKIXCertPathBuilderResult.java
+++ b/libcore/security/src/main/java/java/security/cert/PKIXCertPathBuilderResult.java
@@ -25,8 +25,6 @@
/**
* The result of the PKIX certification path builder, returned by
* {@link CertPathBuilder#build(CertPathParameters)}.
- *
- * @since Android 1.0
*/
public class PKIXCertPathBuilderResult extends PKIXCertPathValidatorResult
implements CertPathBuilderResult {
@@ -49,7 +47,6 @@
* @throws NullPointerException
* if the {@code cerPath}, {@code trustAnchor} or {@code
* subjectPolicyKey} is {@code null}.
- * @since Android 1.0
*/
public PKIXCertPathBuilderResult(CertPath certPath, TrustAnchor trustAnchor,
PolicyNode policyTree, PublicKey subjectPublicKey) {
@@ -64,7 +61,6 @@
* Returns the validated certification path.
*
* @return the validated certification path.
- * @since Android 1.0
*/
public CertPath getCertPath() {
return certPath;
@@ -76,10 +72,9 @@
*
* @return a string representation of this {@code PKIXCertPathBuilderResult}
* instance.
- * @since Android 1.0
*/
public String toString() {
- StringBuffer sb = new StringBuffer(super.toString());
+ StringBuilder sb = new StringBuilder(super.toString());
sb.append("\n Certification Path: "); //$NON-NLS-1$
sb.append(certPath.toString());
sb.append("\n]"); //$NON-NLS-1$
diff --git a/libcore/security/src/main/java/java/security/cert/PKIXCertPathChecker.java b/libcore/security/src/main/java/java/security/cert/PKIXCertPathChecker.java
index 5614878..710ac11 100644
--- a/libcore/security/src/main/java/java/security/cert/PKIXCertPathChecker.java
+++ b/libcore/security/src/main/java/java/security/cert/PKIXCertPathChecker.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Vladimir N. Molotkov
-* @version $Revision$
-*/
-
package java.security.cert;
import java.util.Collection;
@@ -38,22 +33,16 @@
* {@link #check(Certificate, Collection) check} method will be called for each
* certificate processed by a {@code CertPathBuilder} of {@code
* CertPathValidator}.
- * </p>
* <p>
* A {@code PKIXCertPathChecker} implementation <u>must</u> support reverse
* checking (from trusted CA to target) and <u>may</u> support forward checking
* (from target to trusted CA). The return value of {@code
* isForwardCheckingSupported} indicates whether forward checking is supported.
- * </p>
- *
- * @since Android 1.0
*/
public abstract class PKIXCertPathChecker implements Cloneable {
/**
* Creates a new {@code PKIXCertPathChecker} instance.
- *
- * @since Android 1.0
*/
protected PKIXCertPathChecker() {}
@@ -61,7 +50,6 @@
* Clones this {@code PKIXCertPathChecker} instance.
*
* @return the cloned instance.
- * @since Android 1.0
*/
public Object clone() {
try {
@@ -84,7 +72,6 @@
* if initialization of this {@code PKIXCertPathChecker}
* instance fails, or if it cannot process certificates in the
* specified order.
- * @since Android 1.0
*/
public abstract void init(boolean forward)
throws CertPathValidatorException;
@@ -95,7 +82,6 @@
*
* @return {@code true} if this {@code PKIXCertPathChecker} instance
* supports forward checking, otherwise {@code false}.
- * @since Android 1.0
*/
public abstract boolean isForwardCheckingSupported();
@@ -106,7 +92,6 @@
* @return the list of extensions of X.509 certificates that this {@code
* PKIXCertPathChecker} is able to process, or {@code null} if there
* are none.
- * @since Android 1.0
*/
public abstract Set<String> getSupportedExtensions();
@@ -120,7 +105,6 @@
* the list of critical X.509 extension OID strings.
* @throws CertPathValidatorException
* if check(s) fail on the specified certificate.
- * @since Android 1.0
*/
public abstract void check(Certificate cert, Collection<String> unresolvedCritExts)
throws CertPathValidatorException;
diff --git a/libcore/security/src/main/java/java/security/cert/PKIXCertPathValidatorResult.java b/libcore/security/src/main/java/java/security/cert/PKIXCertPathValidatorResult.java
index 21f90c9..7d80ae5 100644
--- a/libcore/security/src/main/java/java/security/cert/PKIXCertPathValidatorResult.java
+++ b/libcore/security/src/main/java/java/security/cert/PKIXCertPathValidatorResult.java
@@ -26,7 +26,6 @@
*
* @see CertPathValidator
* @see CertPathValidator#validate(CertPath, CertPathParameters)
- * @since Android 1.0
*/
public class PKIXCertPathValidatorResult implements CertPathValidatorResult {
// A trust anchor used during validation of certification path
@@ -48,7 +47,6 @@
* the valid policy tree from the validation.
* @param subjectPublicKey
* the subject public key from the validation.
- * @since Android 1.0
*/
public PKIXCertPathValidatorResult(TrustAnchor trustAnchor,
PolicyNode policyTree, PublicKey subjectPublicKey) {
@@ -68,7 +66,6 @@
* Returns the valid policy tree from the validation.
*
* @return the valid policy tree from the validation.
- * @since Android 1.0
*/
public PolicyNode getPolicyTree() {
return policyTree;
@@ -78,7 +75,6 @@
* Returns the subject public key from the validation.
*
* @return the subject public key from the validation.
- * @since Android 1.0
*/
public PublicKey getPublicKey() {
return subjectPublicKey;
@@ -89,7 +85,6 @@
* served as trust anchor for this certification path.
*
* @return the trust anchor.
- * @since Android 1.0
*/
public TrustAnchor getTrustAnchor() {
return trustAnchor;
@@ -99,7 +94,6 @@
* Clones this {@code PKIXCertPathValidatorResult} instance.
*
* @return the cloned instance.
- * @since Android 1.0
*/
public Object clone() {
try {
@@ -116,10 +110,9 @@
*
* @return a string representation for this {@code
* PKIXCertPathValidatorResult} instance.
- * @since Android 1.0
*/
public String toString() {
- StringBuffer sb = new StringBuffer(super.toString());
+ StringBuilder sb = new StringBuilder(super.toString());
sb.append(": [\n Trust Anchor: "); //$NON-NLS-1$
sb.append(trustAnchor.toString());
sb.append("\n Policy Tree: "); //$NON-NLS-1$
diff --git a/libcore/security/src/main/java/java/security/cert/PKIXParameters.java b/libcore/security/src/main/java/java/security/cert/PKIXParameters.java
index 16b0686..4034d21 100644
--- a/libcore/security/src/main/java/java/security/cert/PKIXParameters.java
+++ b/libcore/security/src/main/java/java/security/cert/PKIXParameters.java
@@ -36,11 +36,9 @@
* <p>
* The parameters must be created with <i>trusted</i> certificate authorities
* (trust anchors).
- * </p>
- *
+ *
* @see CertPathValidator
* @see CertPathParameters
- * @since Android 1.0
*/
public class PKIXParameters implements CertPathParameters {
// Set of trust anchors - most trusted CAs
@@ -79,7 +77,6 @@
* the trusted CAs.
* @throws InvalidAlgorithmParameterException
* if {@code trustAnchors} is empty.
- * @since Android 1.0
*/
public PKIXParameters(Set<TrustAnchor> trustAnchors)
throws InvalidAlgorithmParameterException {
@@ -101,7 +98,6 @@
* @throws InvalidAlgorithmParameterException
* if {@code keyStore} does not contained any trusted
* certificate entry.
- * @since Android 1.0
*/
public PKIXParameters(KeyStore keyStore)
throws KeyStoreException,
@@ -137,7 +133,6 @@
* Returns a unmodifiable set of the <i>trusted</i> certificate authorities.
*
* @return a unmodifiable set of the <i>trusted</i> certificate authorities.
- * @since Android 1.0
*/
public Set<TrustAnchor> getTrustAnchors() {
return Collections.unmodifiableSet(trustAnchors);
@@ -150,7 +145,6 @@
* the set of <i>trusted</i> certificate authorities.
* @throws InvalidAlgorithmParameterException
* if {@code trustAnchors} is empty.
- * @since Android 1.0
*/
public void setTrustAnchors(Set<TrustAnchor> trustAnchors)
throws InvalidAlgorithmParameterException {
@@ -169,7 +163,6 @@
*
* @return {@code true} if the <i>any policy OID</i> will be inhibited,
* otherwise {@code false}.
- * @since Android 1.0
*/
public boolean isAnyPolicyInhibited() {
return anyPolicyInhibited;
@@ -182,7 +175,6 @@
* @param anyPolicyInhibited
* {@code true} if the <i>any policy OID</i> should be inhibited,
* otherwise {@code false}.
- * @since Android 1.0
*/
public void setAnyPolicyInhibited(boolean anyPolicyInhibited) {
this.anyPolicyInhibited = anyPolicyInhibited;
@@ -192,10 +184,8 @@
* Returns the list of checkers for the certification path.
* <p>
* The list is unmodifiable and the entries in the list are cloned.
- * </p>
- *
+ *
* @return the list of checkers for the certification path.
- * @since Android 1.0
*/
public List<PKIXCertPathChecker> getCertPathCheckers() {
if (certPathCheckers == null) {
@@ -222,12 +212,10 @@
* Sets the list of checkers for the certification path.
* <p>
* The list is copied and the entries are cloned.
- * </p>
*
* @param certPathCheckers
* the list of checkers for the certification path, or {@code
* null} to clear the checkers.
- * @since Android 1.0
*/
public void setCertPathCheckers(List<PKIXCertPathChecker> certPathCheckers) {
if (certPathCheckers == null || certPathCheckers.isEmpty()) {
@@ -254,7 +242,6 @@
* @param checker
* the {@code PKIXCertPathChecker} to add, if {@code null}, it
* will be ignored.
- * @since Android 1.0
*/
public void addCertPathChecker(PKIXCertPathChecker checker) {
if (checker == null) {
@@ -274,7 +261,6 @@
* and CRLs.
*
* @return an immutable list of certificate stores.
- * @since Android 1.0
*/
public List<CertStore> getCertStores() {
if (certStores == null) {
@@ -298,7 +284,6 @@
* CRLs.
*
* @param certStores the list of certificate stores.
- * @since Android 1.0
*/
public void setCertStores(List<CertStore> certStores) {
if (certStores == null || certStores.isEmpty()) {
@@ -325,7 +310,6 @@
*
* @param store
* the store to add, if {@code null}, it will be ignored.
- * @since Android 1.0
*/
public void addCertStore(CertStore store) {
if (store == null) {
@@ -346,7 +330,6 @@
*
* @return the time for the validation, or {@code null} for the current
* time.
- * @since Android 1.0
*/
public Date getDate() {
return date == null ? null : (Date)date.clone();
@@ -359,7 +342,6 @@
* @param date
* the time for the validation, or {@code null} for the current
* time.
- * @since Android 1.0
*/
public void setDate(Date date) {
this.date = (date == null ? null : new Date(date.getTime()));
@@ -371,7 +353,6 @@
*
* @return {@code true} if an explicit policy is required, otherwise {@code
* false}.
- * @since Android 1.0
*/
public boolean isExplicitPolicyRequired() {
return explicitPolicyRequired;
@@ -384,7 +365,6 @@
* @param explicitPolicyRequired
* {@code true} if an explicit policy is required, otherwise
* {@code false}.
- * @since Android 1.0
*/
public void setExplicitPolicyRequired(boolean explicitPolicyRequired) {
this.explicitPolicyRequired = explicitPolicyRequired;
@@ -396,7 +376,6 @@
*
* @return the unmodifiable list of policies, or an empty set if any policy
* is acceptable.
- * @since Android 1.0
*/
public Set<String> getInitialPolicies() {
if (initialPolicies == null) {
@@ -421,7 +400,6 @@
* @param initialPolicies
* the list of policies, or an empty set or {@code null} if any
* policy is acceptable.
- * @since Android 1.0
*/
public void setInitialPolicies(Set<String> initialPolicies) {
if (initialPolicies == null || initialPolicies.isEmpty()) {
@@ -448,7 +426,6 @@
*
* @return {@code true} if policy mapping is inhibited, otherwise {@code
* false}.
- * @since Android 1.0
*/
public boolean isPolicyMappingInhibited() {
return policyMappingInhibited;
@@ -460,7 +437,6 @@
* @param policyMappingInhibited
* {@code true} if policy mapping is to be inhibited, otherwise
* {@code false}.
- * @since Android 1.0
*/
public void setPolicyMappingInhibited(boolean policyMappingInhibited) {
this.policyMappingInhibited = policyMappingInhibited;
@@ -472,7 +448,6 @@
*
* @return {@code true} if the certificates should be rejected, otherwise
* {@code false}.
- * @since Android 1.0
*/
public boolean getPolicyQualifiersRejected() {
return policyQualifiersRejected;
@@ -485,7 +460,6 @@
* @param policyQualifiersRejected
* {@code true} if the certificates should be rejected, otherwise
* {@code false}.
- * @since Android 1.0
*/
public void setPolicyQualifiersRejected(boolean policyQualifiersRejected) {
this.policyQualifiersRejected = policyQualifiersRejected;
@@ -497,7 +471,6 @@
*
* @return {@code true} if the default revocation checking mechanism is
* used, otherwise {@code false}.
- * @since Android 1.0
*/
public boolean isRevocationEnabled() {
return revocationEnabled;
@@ -510,7 +483,6 @@
* @param revocationEnabled
* {@code true} id the default revocation checking mechanism
* should be used, otherwise {@code false}.
- * @since Android 1.0
*/
public void setRevocationEnabled(boolean revocationEnabled) {
this.revocationEnabled = revocationEnabled;
@@ -521,7 +493,6 @@
*
* @return the name of the signature provider, or {@code null} if none is
* set.
- * @since Android 1.0
*/
public String getSigProvider() {
return sigProvider;
@@ -537,7 +508,6 @@
* @param sigProvider
* the name of the preferred signature provider, or {@code null}
* if none is preferred.
- * @since Android 1.0
*/
public void setSigProvider(String sigProvider) {
this.sigProvider = sigProvider;
@@ -548,7 +518,6 @@
*
* @return the constraints for the target certificate, or {@code null} if
* none are set.
- * @since Android 1.0
*/
public CertSelector getTargetCertConstraints() {
return (targetCertConstraints == null ? null
@@ -561,7 +530,6 @@
* @param targetCertConstraints
* the constraints for the target certificate, or {@code null} if
* none should be used.
- * @since Android 1.0
*/
public void setTargetCertConstraints(CertSelector targetCertConstraints) {
this.targetCertConstraints = (targetCertConstraints == null ? null
@@ -572,7 +540,6 @@
* Clones this {@code PKIXParameters} instance.
*
* @return the cloned instance.
- * @since Android 1.0
*/
public Object clone() {
try {
@@ -595,11 +562,10 @@
* Returns a string representation of this {@code PKIXParameters} instance.
*
* @return a string representation of this {@code PKIXParameters} instance.
- * @since Android 1.0
*/
public String toString() {
- StringBuffer sb =
- new StringBuffer("[\n Trust Anchors: "); //$NON-NLS-1$
+ StringBuilder sb =
+ new StringBuilder("[\n Trust Anchors: "); //$NON-NLS-1$
sb.append(trustAnchors);
sb.append("\n Revocation Enabled: "); //$NON-NLS-1$
sb.append(revocationEnabled);
diff --git a/libcore/security/src/main/java/java/security/cert/PolicyNode.java b/libcore/security/src/main/java/java/security/cert/PolicyNode.java
index c112a8a..c485b69 100644
--- a/libcore/security/src/main/java/java/security/cert/PolicyNode.java
+++ b/libcore/security/src/main/java/java/security/cert/PolicyNode.java
@@ -26,9 +26,6 @@
* <p>
* Instances of this class are one of the outputs of the PKIX certification path
* validation algorithm.
- * </p>
- *
- * @since Android 1.0
*/
public interface PolicyNode {
@@ -36,7 +33,6 @@
* Returns the list of children of this node as an {@code Iterator}.
*
* @return the list of children of this node as an {@code Iterator}.
- * @since Android 1.0
*/
public Iterator<? extends PolicyNode> getChildren();
@@ -44,10 +40,8 @@
* Returns the depth of this node in the policy tree.
* <p>
* the depth is zero based.
- * </p>
*
* @return the depth of this node in the policy tree.
- * @since Android 1.0
*/
public int getDepth();
@@ -55,7 +49,6 @@
* Returns the expected policies for the next certificate to be valid.
*
* @return the expected policies.
- * @since Android 1.0
*/
public Set<String> getExpectedPolicies();
@@ -63,7 +56,6 @@
* Returns the parent policy node.
*
* @return the parent policy node.
- * @since Android 1.0
*/
public PolicyNode getParent();
@@ -71,7 +63,6 @@
* Returns the policy qualifiers associated with the policy of this node.
*
* @return the policy qualifiers associated with the policy of this node.
- * @since Android 1.0
*/
public Set<? extends PolicyQualifierInfo> getPolicyQualifiers();
@@ -79,7 +70,6 @@
* Returns the valid policy of this node.
*
* @return the valid policy of this node.
- * @since Android 1.0
*/
public String getValidPolicy();
@@ -89,7 +79,6 @@
*
* @return {@code true} if the extension is marked as critical, otherwise
* {@code false}.
- * @since Android 1.0
*/
public boolean isCritical();
}
diff --git a/libcore/security/src/main/java/java/security/cert/PolicyQualifierInfo.java b/libcore/security/src/main/java/java/security/cert/PolicyQualifierInfo.java
index 5a63d51..903a6e9 100644
--- a/libcore/security/src/main/java/java/security/cert/PolicyQualifierInfo.java
+++ b/libcore/security/src/main/java/java/security/cert/PolicyQualifierInfo.java
@@ -27,8 +27,6 @@
/**
* This class implements a policy qualifier as defined by the ASN.1
* {@code PolicyQualifierInfo} structure.
- *
- * @since Android 1.0
*/
public class PolicyQualifierInfo {
// This PolicyQualifierInfo DER encoding
@@ -48,7 +46,6 @@
* the DER encoded policy qualifier.
* @throws IOException
* the policy qualifier cannot be decoded.
- * @since Android 1.0
*/
public PolicyQualifierInfo(byte[] encoded) throws IOException {
if (encoded == null) {
@@ -71,7 +68,6 @@
* Returns a ASN.1 DER encoded copy of policy qualifier info.
*
* @return a ASN.1 DER encoded copy of policy qualifier info.
- * @since Android 1.0
*/
public final byte[] getEncoded() {
byte[] ret = new byte[encoded.length];
@@ -83,7 +79,6 @@
* Returns the identifier (an OID) of this policy qualifier info.
*
* @return the identifier of this policy qualifier info.
- * @since Android 1.0
*/
public final String getPolicyQualifierId() {
return policyQualifierId;
@@ -95,7 +90,6 @@
*
* @return a ASN.1 DER encoded copy of the qualifier of this policy
* qualifier info.
- * @since Android 1.0
*/
public final byte[] getPolicyQualifier() {
if (policyQualifier == null) {
@@ -112,11 +106,10 @@
*
* @return a string representation of this {@code PolicyQualifierInfo}
* instance.
- * @since Android 1.0
*/
public String toString() {
- StringBuffer sb =
- new StringBuffer("PolicyQualifierInfo: [\npolicyQualifierId: "); //$NON-NLS-1$
+ StringBuilder sb =
+ new StringBuilder("PolicyQualifierInfo: [\npolicyQualifierId: "); //$NON-NLS-1$
sb.append(policyQualifierId);
sb.append("\npolicyQualifier: \n"); //$NON-NLS-1$
sb.append(Array.toString(policyQualifier, " ")); //$NON-NLS-1$
diff --git a/libcore/security/src/main/java/java/security/cert/TrustAnchor.java b/libcore/security/src/main/java/java/security/cert/TrustAnchor.java
index 9dc2025..eae38d6 100644
--- a/libcore/security/src/main/java/java/security/cert/TrustAnchor.java
+++ b/libcore/security/src/main/java/java/security/cert/TrustAnchor.java
@@ -36,9 +36,6 @@
* of the CA, the CA's name and the constraints for the validation of
* certification paths. The constructor also allows to specify a binary
* representation of a so called "Name Constraints" extension as a byte array.
- * </p>
- *
- * @since Android 1.0
*/
public class TrustAnchor {
// Most trusted CA as a X500Principal
@@ -58,8 +55,7 @@
* <p>
* The name constraints will be used as additional constraints during the
* validation of certification paths.
- * </p>
- *
+ *
* @param trustedCert
* the trusted certificate
* @param nameConstraints
@@ -67,7 +63,6 @@
* null} if none.
* @throws IllegalArgumentException
* if the decoding of the name constraints fail.
- * @since Android 1.0
*/
public TrustAnchor(X509Certificate trustedCert, byte[] nameConstraints) {
if (trustedCert == null) {
@@ -94,8 +89,7 @@
* <p>
* The name constraints will be used as additional constraints during the
* validation of certification paths.
- * </p>
- *
+ *
* @param caName
* the X.500 name of the certificate authority in RFC 2253
* {@code String} format.
@@ -107,7 +101,6 @@
* @throws IllegalArgumentException
* if the {@code caName} is empty or if decoding of the name
* constraints fail.
- * @since Android 1.0
*/
public TrustAnchor(String caName, PublicKey caPublicKey,
byte[] nameConstraints) {
@@ -146,7 +139,6 @@
* <p>
* The name constraints will be used as additional constraints during the
* validation of certification paths.
- * </p>
*
* @param caPrincipal
* the name of the certificate authority as X500 principal.
@@ -157,7 +149,6 @@
* null} if none.
* @throws IllegalArgumentException
* if decoding of the name constraints fail.
- * @since Android 1.0
*/
public TrustAnchor(X500Principal caPrincipal,
PublicKey caPublicKey, byte[] nameConstraints) {
@@ -187,7 +178,6 @@
* Returns a copy of the name constraints in ASN.1 DER encoded form.
*
* @return a copy of the name constraints in ASN.1 DER encoded form.
- * @since Android 1.0
*/
public final byte[] getNameConstraints() {
if (nameConstraints == null) {
@@ -204,7 +194,6 @@
*
* @return the certificate of this CA or {@code null}, if the trust anchor
* of this instance was not created with a certificate.
- * @since Android 1.0
*/
public final X509Certificate getTrustedCert() {
return trustedCert;
@@ -216,7 +205,6 @@
* @return the name of the certificate authority or {@code null} if the
* trust anchor of this instance was not created with a {@code
* X500Principal}.
- * @since Android 1.0
*/
public final X500Principal getCA() {
return caPrincipal;
@@ -229,7 +217,6 @@
* @return the name of the certificate authority as {@code String} in RFC
* 2253 format or {@code null} if the trust anchor of this instance
* was not created with a CA name.
- * @since Android 1.0
*/
public final String getCAName() {
return caName;
@@ -241,7 +228,6 @@
* @return the public key of the certificate authority or {@code null} if
* the trust anchor if this instance was not created with a public
* key.
- * @since Android 1.0
*/
public final PublicKey getCAPublicKey() {
return caPublicKey;
@@ -251,10 +237,9 @@
* Returns a string representation of this {@code TrustAnchor} instance.
*
* @return a string representation of this {@code TrustAnchor} instance.
- * @since Android 1.0
*/
public String toString() {
- StringBuffer sb = new StringBuffer("TrustAnchor: [\n"); //$NON-NLS-1$
+ StringBuilder sb = new StringBuilder("TrustAnchor: [\n"); //$NON-NLS-1$
if (trustedCert != null) {
sb.append("Trusted CA certificate: "); //$NON-NLS-1$
sb.append(trustedCert);
diff --git a/libcore/security/src/main/java/java/security/cert/X509CRL.java b/libcore/security/src/main/java/java/security/cert/X509CRL.java
index eabdb68..cb99843 100644
--- a/libcore/security/src/main/java/java/security/cert/X509CRL.java
+++ b/libcore/security/src/main/java/java/security/cert/X509CRL.java
@@ -44,16 +44,11 @@
* href
* ="http://www.ietf.org/rfc/rfc2459.txt">http://www.ietf.org/rfc/rfc2459.txt
* </a>.
- * </p>
- *
- * @since Android 1.0
*/
public abstract class X509CRL extends CRL implements X509Extension {
/**
* Creates a new {@code X509CRL} instance.
- *
- * @since Android 1.0
*/
protected X509CRL() {
super("X.509"); //$NON-NLS-1$
@@ -66,7 +61,6 @@
* the object to compare.
* @return {@code true} if the specified object is equal to this, otherwise
* {@code false}.
- * @since Android 1.0
*/
public boolean equals(Object other) {
if (other == this) {
@@ -87,7 +81,6 @@
* Returns the hashcode of this CRL instance.
*
* @return the hashcode.
- * @since Android 1.0
*/
public int hashCode() {
try {
@@ -108,7 +101,6 @@
* @return this CRL in ASN.1 DER encoded form.
* @throws CRLException
* if encoding fails.
- * @since Android 1.0
*/
public abstract byte[] getEncoded() throws CRLException;
@@ -129,7 +121,6 @@
* if no provider can be found.
* @throws SignatureException
* if errors occur on signatures.
- * @since Android 1.0
*/
public abstract void verify(PublicKey key)
throws CRLException, NoSuchAlgorithmException,
@@ -155,7 +146,6 @@
* if the specified provider cannot be found.
* @throws SignatureException
* if errors occur on signatures.
- * @since Android 1.0
*/
public abstract void verify(PublicKey key, String sigProvider)
throws CRLException, NoSuchAlgorithmException,
@@ -166,7 +156,6 @@
* Returns the version number of this CRL.
*
* @return the version number of this CRL.
- * @since Android 1.0
*/
public abstract int getVersion();
@@ -175,7 +164,6 @@
* the issuer as an implementation specific Principal object.
*
* @return the issuer distinguished name.
- * @since Android 1.0
*/
public abstract Principal getIssuerDN();
@@ -183,7 +171,6 @@
* Returns the issuer distinguished name of this CRL.
*
* @return the issuer distinguished name of this CRL.
- * @since Android 1.0
*/
public X500Principal getIssuerX500Principal() {
try {
@@ -206,7 +193,6 @@
* Returns the {@code thisUpdate} value of this CRL.
*
* @return the {@code thisUpdate} value of this CRL.
- * @since Android 1.0
*/
public abstract Date getThisUpdate();
@@ -215,7 +201,6 @@
*
* @return the {@code nextUpdate} value of this CRL, or {@code null} if none
* is present.
- * @since Android 1.0
*/
public abstract Date getNextUpdate();
@@ -226,7 +211,6 @@
* the certificate serial number to search for a CRL entry.
* @return the entry for the specified certificate serial number, or {@code
* null} if not found.
- * @since Android 1.0
*/
public abstract X509CRLEntry getRevokedCertificate(BigInteger serialNumber);
@@ -237,7 +221,6 @@
* the certificate to search a CRL entry for.
* @return the entry for the specified certificate, or {@code null} if not
* found.
- * @since Android 1.0
*/
public X509CRLEntry getRevokedCertificate(X509Certificate certificate) {
if (certificate == null) {
@@ -251,7 +234,6 @@
*
* @return the set of revoked certificates, or {@code null} if no revoked
* certificates are in this CRL.
- * @since Android 1.0
*/
public abstract Set<? extends X509CRLEntry> getRevokedCertificates();
@@ -262,7 +244,6 @@
* @return the CRL information in DER encoded form.
* @throws CRLException
* if encoding fails.
- * @since Android 1.0
*/
public abstract byte[] getTBSCertList() throws CRLException;
@@ -270,7 +251,6 @@
* Returns the signature bytes of this CRL.
*
* @return the signature bytes of this CRL.
- * @since Android 1.0
*/
public abstract byte[] getSignature();
@@ -278,7 +258,6 @@
* Returns the name of the signature algorithm.
*
* @return the name of the signature algorithm.
- * @since Android 1.0
*/
public abstract String getSigAlgName();
@@ -286,7 +265,6 @@
* Returns the OID of the signature algorithm.
*
* @return the OID of the signature algorithm.
- * @since Android 1.0
*/
public abstract String getSigAlgOID();
@@ -295,7 +273,6 @@
*
* @return the parameters of the signature algorithm in DER encoded form, or
* {@code null} if not present.
- * @since Android 1.0
*/
public abstract byte[] getSigAlgParams();
}
diff --git a/libcore/security/src/main/java/java/security/cert/X509CRLEntry.java b/libcore/security/src/main/java/java/security/cert/X509CRLEntry.java
index 35fb78b..ccdaf2f 100644
--- a/libcore/security/src/main/java/java/security/cert/X509CRLEntry.java
+++ b/libcore/security/src/main/java/java/security/cert/X509CRLEntry.java
@@ -29,14 +29,11 @@
* Abstract base class for entries in a certificate revocation list (CRL).
*
* @see X509CRL
- * @since Android 1.0
*/
public abstract class X509CRLEntry implements X509Extension {
/**
* Creates a new {@code X509CRLEntry} instance.
- *
- * @since Android 1.0
*/
public X509CRLEntry() {}
@@ -47,7 +44,6 @@
* the object to compare.
* @return {@code true} if the specified object equals to this instance,
* otherwise {@code false}.
- * @since Android 1.0
*/
public boolean equals(Object other) {
if (other == this) {
@@ -68,7 +64,6 @@
* Returns the hashcode of this instance.
*
* @return the hashcode of this instance.
- * @since Android 1.0
*/
public int hashCode() {
int res = 0;
@@ -88,7 +83,6 @@
* @return the encoded form of this entry.
* @throws CRLException
* if encoding fails.
- * @since Android 1.0
*/
public abstract byte[] getEncoded() throws CRLException;
@@ -96,7 +90,6 @@
* Returns the serial number of the revoked certificate.
*
* @return the serial number of the revoked certificate.
- * @since Android 1.0
*/
public abstract BigInteger getSerialNumber();
@@ -105,7 +98,6 @@
*
* @return the issuer of the revoked certificate, or {@code null} if the
* issuer is equal to the CRL issuer.
- * @since Android 1.0
*/
public X500Principal getCertificateIssuer() {
return null;
@@ -115,7 +107,6 @@
* Returns the date when the certificate is revoked.
*
* @return the date when the certificate is revoked.
- * @since Android 1.0
*/
public abstract Date getRevocationDate();
@@ -124,7 +115,6 @@
*
* @return {@code true} is this CRL entry has extensions, otherwise {@code
* false}.
- * @since Android 1.0
*/
public abstract boolean hasExtensions();
@@ -132,7 +122,6 @@
* Returns a string representation of this instance.
*
* @return a string representation of this instance.
- * @since Android 1.0
*/
public abstract String toString();
}
diff --git a/libcore/security/src/main/java/java/security/cert/X509CRLSelector.java b/libcore/security/src/main/java/java/security/cert/X509CRLSelector.java
index c1b5f45..0edddf4 100644
--- a/libcore/security/src/main/java/java/security/cert/X509CRLSelector.java
+++ b/libcore/security/src/main/java/java/security/cert/X509CRLSelector.java
@@ -36,10 +36,7 @@
* X509CRL}s that match the specified criteria.
* <p>
* When constructed, all criteria are set to default values that will match any
- * {@code X509CRL}.
- * </p>
- *
- * @since Android 1.0
+ * {@code X509CRL}.
*/
public class X509CRLSelector implements CRLSelector {
@@ -60,8 +57,6 @@
/**
* Creates a new {@code X509CertSelector}.
- *
- * @since Android 1.0
*/
public X509CRLSelector() { }
@@ -70,12 +65,10 @@
* <p>
* The CRL issuer must match at least one of the specified distinguished
* names.
- * </p>
- *
+ *
* @param issuers
* the list of issuer distinguished names to match, or {@code
* null} if any issuer distinguished name will do.
- * @since Android 1.0
*/
public void setIssuers(Collection<X500Principal> issuers) {
if (issuers == null) {
@@ -97,20 +90,17 @@
* <p>
* The CRL issuer must match at least one of the specified distinguished
* names.
- * </p>
* <p>
* The specified parameter {@code names} is a collection with an entry for
* each name to be included in the criterion. The name is specified as a
* {@code String} or a byte array specifying the name (in RFC 2253 or ASN.1
* DER encoded form)
- * </p>
- *
+ *
* @param names
* the list of issuer distinguished names to match, or {@code
* null} if any issuer distinguished name will do.
* @throws IOException
* if parsing fails.
- * @since Android 1.0
*/
public void setIssuerNames(Collection<?> names) throws IOException {
if (names == null) {
@@ -143,11 +133,9 @@
* <p>
* The CRL issuer must match at least one of the specified distinguished
* names.
- * </p>
- *
+ *
* @param issuer
* the issuer to add to the criterion
- * @since Android 1.0
*/
public void addIssuer(X500Principal issuer) {
if (issuer == null) {
@@ -178,13 +166,11 @@
* <p>
* Adds an issuer to the criterion for the issuer distinguished names. The
* CRK issuer must match at least one of the specified distinguished names.
- * </p>
- *
+ *
* @param iss_name
* the RFC 2253 encoded name.
* @throws IOException
* if parsing fails.
- * @since Android 1.0
*/
public void addIssuerName(String iss_name) throws IOException {
if (issuerNames == null) {
@@ -206,13 +192,11 @@
* <p>
* The CRL issuer must match at least one of the specified distinguished
* names.
- * </p>
- *
+ *
* @param iss_name
* the issuer to add to the criterion in ASN.1 DER encoded form.
* @throws IOException
* if parsing fails.
- * @since Android 1.0
*/
public void addIssuerName(byte[] iss_name) throws IOException {
if (iss_name == null) {
@@ -232,12 +216,10 @@
* <p>
* The CRL must have a number extension with a value greater than or equal
* to the specified parameter.
- * </p>
- *
+ *
* @param minCRL
* the minimum CRL number or null to not check the minimum CRL
* number
- * @since Android 1.0
*/
public void setMinCRLNumber(BigInteger minCRL) {
this.minCRL = minCRL;
@@ -248,12 +230,10 @@
* <p>
* The CRL must have a number extension with a value less than or equal to
* the specified parameter.
- * </p>
- *
+ *
* @param maxCRL
* the maximum CRL number or null to not check the maximum CRL
* number.
- * @since Android 1.0
*/
public void setMaxCRLNumber(BigInteger maxCRL) {
this.maxCRL = maxCRL;
@@ -264,12 +244,10 @@
* <p>
* The CRL's {@code thisUpdate} value must be equal or before the specified
* date and the {@code nextUpdate} value must be after the specified date.
- * </p>
- *
+ *
* @param dateAndTime
* the date to search for valid CRL's or {@code null} to not
* check the date.
- * @since Android 1.0
*/
public void setDateAndTime(Date dateAndTime) {
if (dateAndTime == null) {
@@ -282,10 +260,9 @@
/**
* Sets a certificate hint to find CRLs. It's not a criterion but may help
* finding relevant CRLs.
- *
+ *
* @param cert
* the certificate hint or {@code null}.
- * @since Android 1.0
*/
public void setCertificateChecking(X509Certificate cert) {
this.certificateChecking = cert;
@@ -295,11 +272,9 @@
* Returns the criterion for the issuer distinguished names.
* <p>
* The CRL issuer must match at least one of the distinguished names.
- * </p>
- *
+ *
* @return the unmodifiable list of issuer distinguished names to match, or
* {@code null} if any issuer distinguished name will do.
- * @since Android 1.0
*/
public Collection<X500Principal> getIssuers() {
if (issuerNames == null) {
@@ -320,11 +295,9 @@
* Returns the criterion for the issuer distinguished names.
* <p>
* The CRL issuer must match at least one of the distinguished names.
- * </p>
- *
+ *
* @return a copy of the list of issuer distinguished names to match, or
* {@code null} if any issuer distinguished name will do.
- * @since Android 1.0
*/
public Collection<Object> getIssuerNames() {
if (issuerNames == null) {
@@ -338,11 +311,9 @@
* <p>
* The CRL must have a number extension with a value greater than or equal
* to the returned value.
- * </p>
- *
+ *
* @return the minimum CRL number or {@code null} if the minimum CRL number
* is not to be checked.
- * @since Android 1.0
*/
public BigInteger getMinCRL() {
return minCRL;
@@ -353,11 +324,9 @@
* <p>
* The CRL must have a number extension with a value less than or equal to
* the returned value.
- * </p>
- *
+ *
* @return the maximum CRL number or null if the maximum CRL number is not
* checked.
- * @since Android 1.0
*/
public BigInteger getMaxCRL() {
return maxCRL;
@@ -368,11 +337,9 @@
* <p>
* The CRL's {@code thisUpdate} value must be equal or before the returned
* date and the {@code nextUpdate} value must be after the returned date.
- * </p>
- *
+ *
* @return the date to search for valid CRL's or {@code null} if the date is
* not checked.
- * @since Android 1.0
*/
public Date getDateAndTime() {
if (dateAndTime == -1) {
@@ -384,9 +351,8 @@
/**
* Returns the certificate hint to find CRLs. It's not a criterion but may
* help finding relevant CRLs.
- *
+ *
* @return the certificate hint or {@code null} if none set.
- * @since Android 1.0
*/
public X509Certificate getCertificateChecking() {
return certificateChecking;
@@ -394,12 +360,11 @@
/**
* Returns a string representation of this {@code X509CRLSelector} instance.
- *
+ *
* @return a string representation of this {@code X509CRLSelector} instance.
- * @since Android 1.0
*/
public String toString() {
- StringBuffer result = new StringBuffer();
+ StringBuilder result = new StringBuilder();
result.append("X509CRLSelector:\n["); //$NON-NLS-1$
if (issuerNames != null) {
result.append("\n IssuerNames:\n ["); //$NON-NLS-1$
@@ -429,12 +394,11 @@
/**
* Returns whether the specified CRL matches all the criteria collected in
* this instance.
- *
+ *
* @param crl
* the CRL to check.
* @return {@code true} if the CRL matches all the criteria, otherwise
* {@code false}.
- * @since Android 1.0
*/
public boolean match(CRL crl) {
if (!(crl instanceof X509CRL)) {
@@ -482,19 +446,20 @@
/**
* Clones this {@code X509CRL} instance.
- *
+ *
* @return the cloned instance.
- * @since Android 1.0
*/
public Object clone() {
- X509CRLSelector result = new X509CRLSelector();
- if (issuerNames != null) {
- result.issuerNames = new ArrayList<String>(issuerNames);
- }
- result.minCRL = minCRL;
- result.maxCRL = maxCRL;
- result.dateAndTime = dateAndTime;
- result.certificateChecking = certificateChecking;
+ X509CRLSelector result;
+
+ try {
+ result = (X509CRLSelector) super.clone();
+ if (issuerNames != null) {
+ result.issuerNames = new ArrayList<String>(issuerNames);
+ }
+ } catch (CloneNotSupportedException e) {
+ result = null;
+ }
return result;
}
}
diff --git a/libcore/security/src/main/java/java/security/cert/X509CertSelector.java b/libcore/security/src/main/java/java/security/cert/X509CertSelector.java
index c6d2e98..e2de95b 100644
--- a/libcore/security/src/main/java/java/security/cert/X509CertSelector.java
+++ b/libcore/security/src/main/java/java/security/cert/X509CertSelector.java
@@ -49,8 +49,6 @@
/**
* A certificate selector ({@code CertSelector} for selecting {@code
* X509Certificate}s that match the specified criteria.
- *
- * @since Android 1.0
*/
public class X509CertSelector implements CertSelector {
@@ -81,17 +79,14 @@
/**
* Creates a new {@code X509CertSelector}.
- *
- * @since Android 1.0
*/
public X509CertSelector() {}
/**
* Sets the certificate that a matching certificate must be equal to.
- *
+ *
* @param certificate
* the certificate to match, or null to not check this criteria.
- * @since Android 1.0
*/
public void setCertificate(X509Certificate certificate) {
certificateEquals = certificate;
@@ -99,10 +94,9 @@
/**
* Returns the certificate that a matching certificate must be equal to.
- *
+ *
* @return the certificate to match, or null if this criteria is not
* checked.
- * @since Android 1.0
*/
public X509Certificate getCertificate() {
return certificateEquals;
@@ -110,11 +104,10 @@
/**
* Sets the serial number that a certificate must match.
- *
+ *
* @param serialNumber
* the serial number to match, or {@code null} to not check the
* serial number.
- * @since Android 1.0
*/
public void setSerialNumber(BigInteger serialNumber) {
this.serialNumber = serialNumber;
@@ -122,10 +115,9 @@
/**
* Returns the serial number that a certificate must match.
- *
+ *
* @return the serial number to match, or {@code null} if the serial number
* is not to be checked.
- * @since Android 1.0
*/
public BigInteger getSerialNumber() {
return serialNumber;
@@ -133,11 +125,10 @@
/**
* Sets the issuer that a certificate must match.
- *
+ *
* @param issuer
* the issuer to match, or {@code null} if the issuer is not to
* be checked.
- * @since Android 1.0
*/
public void setIssuer(X500Principal issuer) {
this.issuer = issuer;
@@ -147,10 +138,9 @@
/**
* Returns the issuer that a certificate must match.
- *
+ *
* @return the issuer that a certificate must match, or {@code null} if the
* issuer is not to be checked.
- * @since Android 1.0
*/
public X500Principal getIssuer() {
return issuer;
@@ -160,13 +150,12 @@
* <b>Do not use</b>, use {@link #getIssuer()} or
* {@link #getIssuerAsBytes()} instead. Sets the issuer that a certificate
* must match.
- *
+ *
* @param issuerName
* the issuer in a RFC 2253 format string, or {@code null} to not
* check the issuer.
* @throws IOException
* if parsing the issuer fails.
- * @since Android 1.0
*/
public void setIssuer(String issuerName) throws IOException {
if (issuerName == null) {
@@ -188,10 +177,9 @@
* <b>Do not use</b>, use {@link #getIssuer()} or
* {@link #getIssuerAsBytes()} instead. Returns the issuer that a
* certificate must match in a RFC 2253 format string.
- *
+ *
* @return the issuer in a RFC 2253 format string, or {@code null} if the
* issuer is not to be checked.
- * @since Android 1.0
*/
public String getIssuerAsString() {
if (issuer == null) {
@@ -205,13 +193,12 @@
/**
* Sets the issuer that a certificate must match.
- *
+ *
* @param issuerDN
* the distinguished issuer name in ASN.1 DER encoded format, or
* {@code null} to not check the issuer.
* @throws IOException
* if decoding the issuer fail.
- * @since Android 1.0
*/
public void setIssuer(byte[] issuerDN) throws IOException {
if (issuerDN == null) {
@@ -230,12 +217,11 @@
/**
* Returns the issuer that a certificate must match.
- *
+ *
* @return the distinguished issuer name in ASN.1 DER encoded format, or
* {@code null} if the issuer is not to be checked.
* @throws IOException
* if encoding the issuer fails.
- * @since Android 1.0
*/
public byte[] getIssuerAsBytes() throws IOException {
if (issuer == null) {
@@ -251,11 +237,10 @@
/**
* Set the subject that a certificate must match.
- *
+ *
* @param subject
* the subject distinguished name or {@code null} to not check
* the subject.
- * @since Android 1.0
*/
public void setSubject(X500Principal subject) {
this.subject = subject;
@@ -263,10 +248,9 @@
/**
* Returns the subject that a certificate must match.
- *
+ *
* @return the subject distinguished name, or null if the subject is not to
* be checked.
- * @since Android 1.0
*/
public X500Principal getSubject() {
return subject;
@@ -276,13 +260,12 @@
* <b>Do not use</b>, use {@link #setSubject(byte[])} or
* {@link #setSubject(X500Principal)} instead. Returns the subject that a
* certificate must match.
- *
+ *
* @param subjectDN
* the subject distinguished name in RFC 2253 format or {@code
* null} to not check the subject.
* @throws IOException
* if decoding the subject fails.
- * @since Android 1.0
*/
public void setSubject(String subjectDN) throws IOException {
if (subjectDN == null) {
@@ -300,10 +283,9 @@
* <b>Do not use</b>, use {@link #getSubject()} or
* {@link #getSubjectAsBytes()} instead. Returns the subject that a
* certificate must match.
- *
+ *
* @return the subject distinguished name in RFC 2253 format, or {@code
* null} if the subject is not to be checked.
- * @since Android 1.0
*/
public String getSubjectAsString() {
if (subject == null) {
@@ -314,13 +296,12 @@
/**
* Sets the subject that a certificate must match.
- *
+ *
* @param subjectDN
* the subject distinguished name in ASN.1 DER format, or {@code
* null} to not check the subject.
* @throws IOException
* if decoding the subject fails.
- * @since Android 1.0
*/
public void setSubject(byte[] subjectDN) throws IOException {
if (subjectDN == null) {
@@ -336,12 +317,11 @@
/**
* Returns the subject that a certificate must match.
- *
+ *
* @return the subject distinguished name in ASN.1 DER format, or {@code
* null} if the subject is not to be checked.
* @throws IOException
* if encoding the subject fails.
- * @since Android 1.0
*/
public byte[] getSubjectAsBytes() throws IOException {
if (subject == null) {
@@ -354,12 +334,10 @@
* Sets the criterion for the {@literal SubjectKeyIdentifier} extension.
* <p>
* The {@code subjectKeyIdentifier} should be a single DER encoded value.
- * </p>
- *
+ *
* @param subjectKeyIdentifier
* the subject key identifier or {@code null} to disable this
* check.
- * @since Android 1.0
*/
public void setSubjectKeyIdentifier(byte[] subjectKeyIdentifier) {
if (subjectKeyIdentifier == null) {
@@ -373,10 +351,9 @@
/**
* Returns the criterion for the {@literal SubjectKeyIdentifier} extension.
- *
+ *
* @return the subject key identifier or {@code null} if it is not to be
* checked.
- * @since Android 1.0
*/
public byte[] getSubjectKeyIdentifier() {
if (subjectKeyIdentifier == null) {
@@ -389,11 +366,10 @@
/**
* Sets the criterion for the {@literal AuthorityKeyIdentifier} extension.
- *
+ *
* @param authorityKeyIdentifier
* the authority key identifier, or {@code null} to disable this
* check.
- * @since Android 1.0
*/
public void setAuthorityKeyIdentifier(byte[] authorityKeyIdentifier) {
if (authorityKeyIdentifier == null) {
@@ -409,10 +385,9 @@
/**
* Returns the criterion for the {@literal AuthorityKeyIdentifier}
* extension.
- *
+ *
* @return the authority key identifier, or {@code null} if it is not to be
* checked.
- * @since Android 1.0
*/
public byte[] getAuthorityKeyIdentifier() {
if (authorityKeyIdentifier == null) {
@@ -427,10 +402,8 @@
* Sets the criterion for the validity date of the certificate.
* <p>
* The certificate must be valid at the specified date.
- * </p>
* @param certificateValid
* the validity date or {@code null} to not check the date.
- * @since Android 1.0
*/
public void setCertificateValid(Date certificateValid) {
this.certificateValid = (certificateValid == null)
@@ -440,10 +413,9 @@
/**
* Returns the criterion for the validity date of the certificate.
- *
+ *
* @return the validity date or {@code null} if the date is not to be
* checked.
- * @since Android 1.0
*/
public Date getCertificateValid() {
return (certificateValid == null)
@@ -455,11 +427,9 @@
* Sets the criterion for the validity date of the private key.
* <p>
* The private key must be valid at the specified date.
- * </p>
- *
+ *
* @param privateKeyValid
* the validity date or {@code null} to not check the date.
- * @since Android 1.0
*/
public void setPrivateKeyValid(Date privateKeyValid) {
if (privateKeyValid == null) {
@@ -473,11 +443,9 @@
* Returns the criterion for the validity date of the private key.
* <p>
* The private key must be valid at the specified date.
- * </p>
- *
+ *
* @return the validity date or {@code null} if the date is not to be
* checked.
- * @since Android 1.0
*/
public Date getPrivateKeyValid() {
if (privateKeyValid != null) {
@@ -512,14 +480,12 @@
* <p>
* The certificate must contain a subject public key with the algorithm
* specified.
- * </p>
- *
+ *
* @param oid
* the OID (object identifier) of the signature algorithm or
* {@code null} to not check the OID.
* @throws IOException
* if the specified object identifier is invalid.
- * @since Android 1.0
*/
public void setSubjectPublicKeyAlgID(String oid) throws IOException {
if (oid == null) {
@@ -532,10 +498,9 @@
/**
* Returns the criterion for the subject public key signature algorithm.
- *
+ *
* @return the OID (object identifier) or the signature algorithm or {@code
* null} if it's not to be checked.
- * @since Android 1.0
*/
public String getSubjectPublicKeyAlgID() {
return subjectPublicKeyAlgID;
@@ -543,10 +508,9 @@
/**
* Sets the criterion for the subject public key.
- *
+ *
* @param key
* the subject public key or {@code null} to not check the key.
- * @since Android 1.0
*/
public void setSubjectPublicKey(PublicKey key) {
subjectPublicKey = (key == null) ? null : key.getEncoded();
@@ -555,13 +519,12 @@
/**
* Sets the criterion for the subject public key.
- *
+ *
* @param key
* the subject public key in ASN.1 DER encoded format or {@code null} to
* not check the key.
* @throws IOException
* if decoding the the public key fails.
- * @since Android 1.0
*/
public void setSubjectPublicKey(byte[] key) throws IOException {
if (key == null) {
@@ -578,10 +541,9 @@
/**
* Returns the criterion for the subject public key.
- *
+ *
* @return the subject public key or {@code null} if the key is not to be
* checked.
- * @since Android 1.0
*/
public PublicKey getSubjectPublicKey() {
return subjectPublicKeyImpl;
@@ -589,12 +551,11 @@
/**
* Sets the criterion for the {@literal KeyUsage} extension.
- *
+ *
* @param keyUsage
* the boolean array in the format as returned by
* {@link X509Certificate#getKeyUsage()}, or {@code null} to not
* check the key usage.
- * @since Android 1.0
*/
public void setKeyUsage(boolean[] keyUsage) {
if (keyUsage == null) {
@@ -607,11 +568,10 @@
/**
* Returns the criterion for the {@literal KeyUsage} extension.
- *
+ *
* @return the boolean array in the format as returned by
* {@link X509Certificate#getKeyUsage()}, or {@code null} if the key
* usage is not to be checked.
- * @since Android 1.0
*/
public boolean[] getKeyUsage() {
if (keyUsage == null) {
@@ -624,12 +584,11 @@
/**
* Sets the criterion for the {@literal ExtendedKeyUsage} extension.
- *
+ *
* @param keyUsage
* the set of key usage OIDs, or {@code null} to not check it.
* @throws IOException
* if one of the OIDs is invalid.
- * @since Android 1.0
*/
public void setExtendedKeyUsage(Set<String> keyUsage)
throws IOException {
@@ -649,10 +608,9 @@
/**
* Returns the criterion for the {@literal ExtendedKeyUsage} extension.
- *
+ *
* @return the set of key usage OIDs, or {@code null} if it's not to be
* checked.
- * @since Android 1.0
*/
public Set<String> getExtendedKeyUsage() {
return extendedKeyUsage;
@@ -662,15 +620,12 @@
* Sets the flag for the matching behavior for subject alternative names.
* <p>
* The flag indicates whether a certificate must contain all or at least one
- * of the subject alternative names specified by
- * {@link #setSubjectAlternativeNames} or {@link #addSubjectAlternativeName}
- * .
- * </p>
- *
+ * of the subject alternative names specified by {@link
+ * #setSubjectAlternativeNames} or {@link #addSubjectAlternativeName}.
+ *
* @param matchAllNames
* {@code true} if a certificate must contain all of the
* specified subject alternative names, otherwise {@code false}.
- * @since Android 1.0
*/
public void setMatchAllSubjectAltNames(boolean matchAllNames) {
this.matchAllNames = matchAllNames;
@@ -680,14 +635,11 @@
* Returns the flag for the matching behavior for subject alternative names.
* <p>
* The flag indicates whether a certificate must contain all or at least one
- * of the subject alternative names specified by
- * {@link #setSubjectAlternativeNames} or {@link #addSubjectAlternativeName}
- * .
- * </p>
- *
+ * of the subject alternative names specified by {@link
+ * #setSubjectAlternativeNames} or {@link #addSubjectAlternativeName}.
+ *
* @return {@code true} if a certificate must contain all of the specified
* subject alternative names, otherwise {@code false}.
- * @since Android 1.0
*/
public boolean getMatchAllSubjectAltNames() {
return matchAllNames;
@@ -699,20 +651,17 @@
* the certificate must contain all or at least one of the specified subject
* alternative names. The behavior is specified by
* {@link #getMatchAllSubjectAltNames}.
- * </p>
* <p>
* The specified parameter {@code names} is a collection with an entry for
* each name to be included in the criterion. The name is specified as a
* {@code List}, the first entry must be an {@code Integer} specifying the
* name type (0-8), the second entry must be a {@code String} or a byte
* array specifying the name (in string or ASN.1 DER encoded form)
- * </p>
- *
+ *
* @param names
* the names collection or {@code null} to not perform this check.
* @throws IOException
* if the decoding of a name fails.
- * @since Android 1.0
*/
public void setSubjectAlternativeNames(Collection<List<?>> names)
throws IOException {
@@ -737,14 +686,13 @@
/**
* Adds a subject alternative name to the respective criterion.
- *
+ *
* @param tag
* the type of the name
* @param name
* the name in string format.
* @throws IOException
* if parsing the name fails.
- * @since Android 1.0
*/
public void addSubjectAlternativeName(int tag, String name)
throws IOException {
@@ -761,14 +709,13 @@
/**
* Adds a subject alternative name to the respective criterion.
- *
+ *
* @param tag
* the type of the name.
* @param name
* the name in ASN.1 DER encoded form.
* @throws IOException
* if the decoding of the name fails.
- * @since Android 1.0
*/
public void addSubjectAlternativeName(int tag, byte[] name)
throws IOException {
@@ -789,16 +736,13 @@
* the certificate must contain all or at least one of the specified subject
* alternative names. The behavior is specified by
* {@link #getMatchAllSubjectAltNames}.
- * </p>
* <p>
* The subject alternative names is a collection with an entry for each name
* included in the criterion. The name is specified as a {@code List}, the
* first entry is an {@code Integer} specifying the name type (0-8), the
* second entry is byte array specifying the name in ASN.1 DER encoded form)
- * </p>
- *
+ *
* @return the names collection or {@code null} if none specified.
- * @since Android 1.0
*/
public Collection<List<?>> getSubjectAlternativeNames() {
if (subjectAltNames == null) {
@@ -830,24 +774,23 @@
* <p>
* The certificate must constraint subject and subject alternative names
* that match the specified name constraints.
- * </p>
* <p>
* The name constraints in ASN.1:
- *
+ *
* <pre>
* NameConstraints ::= SEQUENCE {
* permittedSubtrees [0] GeneralSubtrees OPTIONAL,
* excludedSubtrees [1] GeneralSubtrees OPTIONAL }
- *
+ *
* GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
- *
+ *
* GeneralSubtree ::= SEQUENCE {
* base GeneralName,
* minimum [0] BaseDistance DEFAULT 0,
* maximum [1] BaseDistance OPTIONAL }
- *
+ *
* BaseDistance ::= INTEGER (0..MAX)
- *
+ *
* GeneralName ::= CHOICE {
* otherName [0] OtherName,
* rfc822Name [1] IA5String,
@@ -858,17 +801,14 @@
* uniformResourceIdentifier [6] IA5String,
* iPAddress [7] OCTET STRING,
* registeredID [8] OBJECT IDENTIFIER}
- *
+ *
* </pre>
- *
- * </p>
- *
+ *
* @param bytes
* the name constraints in ASN.1 DER encoded format, or null to
* not check any constraints.
* @throws IOException
* if decoding the name constraints fail.
- * @since Android 1.0
*/
public void setNameConstraints(byte[] bytes) throws IOException {
this.nameConstraints = (bytes == null)
@@ -878,10 +818,9 @@
/**
* Returns the criterion for the name constraints.
- *
+ *
* @return the name constraints or {@code null} if none specified.
* @see #setNameConstraints
- * @since Android 1.0
*/
public byte[] getNameConstraints() {
return (nameConstraints == null)
@@ -896,11 +835,9 @@
* include a basic constraints extension with a path length of a least that
* value. A value of {@code -2} indicates that only end-entity certificates
* are accepted. A value of {@code -1} indicates that no check is done.
- * </p>
- *
+ *
* @param pathLen
* the value specifying the criterion.
- * @since Android 1.0
* @throws IllegalArgumentException
* if {@code pathLen} is less than {@code -2}.
*/
@@ -918,10 +855,8 @@
* include a basic constraints extension with a path length of a least that
* value. A value of {@code -2} indicates that only end-entity certificates
* are accepted. A value of {@code -1} indicates that no check is done.
- * </p>
- *
+ *
* @return the value of the criterion.
- * @since Android 1.0
*/
public int getBasicConstraints() {
return pathLen;
@@ -933,14 +868,12 @@
* The certificate must have at least one of the specified certificate
* policy extensions. For an empty set the certificate must have at least
* some policies in its policy extension.
- * </p>
- *
+ *
* @param policies
* the certificate policy OIDs, an empty set, or {@code null} to
* not perform this check.
* @throws IOException
* if parsing the specified OIDs fails.
- * @since Android 1.0
*/
public void setPolicy(Set<String> policies) throws IOException {
if (policies == null) {
@@ -963,11 +896,9 @@
* The certificate must have at least one of the certificate policy
* extensions. For an empty set the certificate must have at least some
* policies in its policy extension.
- * </p>
- *
+ *
* @return the certificate policy OIDs, an empty set, or {@code null} if not
* to be checked.
- * @since Android 1.0
*/
public Set<String> getPolicy() {
return policies;
@@ -978,21 +909,18 @@
* <p>
* This allows to specify the complete set of names, a certificate's name
* constraints must permit.
- * </p>
* <p>
* The specified parameter {@code names} is a collection with an entry for
* each name to be included in the criterion. The name is specified as a
* {@code List}, the first entry must be an {@code Integer} specifying the
* name type (0-8), the second entry must be a {@code String} or a byte
* array specifying the name (in string or ASN.1 DER encoded form)
- * </p>
- *
+ *
* @param names
* the names collection or {@code null} to not perform this
* check.
* @throws IOException
* if decoding fails.
- * @since Android 1.0
*/
public void setPathToNames(Collection<List<?>> names)
throws IOException {
@@ -1017,7 +945,7 @@
/**
* Adds a {@literal "pathToName"} to the respective criterion.
- *
+ *
* @param type
* the type of the name.
* @param name
@@ -1025,7 +953,6 @@
* @throws IOException
* if parsing fails.
* @see #setPathToNames
- * @since Android 1.0
*/
public void addPathToName(int type, String name) throws IOException {
GeneralName path_name = new GeneralName(type, name);
@@ -1038,7 +965,7 @@
/**
* Adds a {@literal "pathToName"} to the respective criterion.
- *
+ *
* @param type
* the type of the name
* @param name
@@ -1046,7 +973,6 @@
* @throws IOException
* if decoding fails.
* @see #setPathToNames
- * @since Android 1.0
*/
public void addPathToName(int type, byte[] name) throws IOException {
GeneralName path_name= new GeneralName(type, name);
@@ -1064,10 +990,8 @@
* in the criterion. The name is specified as a {@code List}, the first
* entry is an {@code Integer} specifying the name type (0-8), the second
* entry is a byte array specifying the name in ASN.1 DER encoded form.
- * </p>
- *
+ *
* @return the pathToNames constraint or {@code null} if none specified.
- * @since Android 1.0
*/
public Collection<List<?>> getPathToNames() {
if (pathToNames == null) {
@@ -1085,17 +1009,16 @@
/**
* Returns a string representation of this {@code X509CertSelector}
* instance.
- *
+ *
* @return a string representation of this {@code X509CertSelector}
* instance.
- * @since Android 1.0
*/
public String toString() {
// For convenient reading of the string representation
// all of the fields named according to the rfc 3280
// (http://www.ietf.org/rfc/rfc3280.txt).
- StringBuffer result = new StringBuffer();
+ StringBuilder result = new StringBuilder();
result.append("X509CertSelector: \n["); //$NON-NLS-1$
if (this.certificateEquals != null) {
result.append("\n certificateEquals: " + certificateEquals); //$NON-NLS-1$
@@ -1210,12 +1133,11 @@
/**
* Returns whether the specified certificate matches all the criteria
* collected in this instance.
- *
+ *
* @param certificate
* the certificate to check.
* @return {@code true} if the certificate matches all the criteria,
* otherwise {@code false}.
- * @since Android 1.0
*/
public boolean match(Certificate certificate) {
if (! (certificate instanceof X509Certificate)) {
@@ -1452,16 +1374,18 @@
/**
* Clones this {@code X509CertSelector} instance.
- *
+ *
* @return the cloned instance.
- * @since Android 1.0
*/
public Object clone() {
- X509CertSelector result = new X509CertSelector();
- result.certificateEquals = this.certificateEquals;
- result.serialNumber = this.serialNumber;
- result.issuer = this.issuer;
- result.subject = this.subject;
+ X509CertSelector result;
+
+ try {
+ result = (X509CertSelector) super.clone();
+ } catch (CloneNotSupportedException e) {
+ return null;
+ }
+
if (this.subjectKeyIdentifier != null) {
result.subjectKeyIdentifier =
new byte[this.subjectKeyIdentifier.length];
@@ -1476,9 +1400,6 @@
result.authorityKeyIdentifier, 0,
this.authorityKeyIdentifier.length);
}
- result.certificateValid = this.certificateValid;
- result.subjectPublicKeyAlgID = this.subjectPublicKeyAlgID;
- result.privateKeyValid = this.privateKeyValid;
if (this.subjectPublicKey != null) {
result.subjectPublicKey = new byte[this.subjectPublicKey.length];
System.arraycopy(this.subjectPublicKey, 0, result.subjectPublicKey,
@@ -1492,8 +1413,6 @@
result.extendedKeyUsage = (this.extendedKeyUsage == null)
? null
: new HashSet(this.extendedKeyUsage);
- result.matchAllNames = this.matchAllNames;
- result.pathLen = this.pathLen;
if (this.subjectAltNames != null) {
result.subjectAltNames = new ArrayList[9];
for (int i=0; i<9; i++) {
@@ -1503,15 +1422,12 @@
}
}
}
- result.nameConstraints = this.nameConstraints;
result.policies = (this.policies == null)
? null
: new HashSet(this.policies);
result.pathToNames = (this.pathToNames == null)
? null
: new ArrayList(this.pathToNames);
- result.subjectPublicKeyImpl = this.subjectPublicKeyImpl;
-
return result;
}
}
diff --git a/libcore/security/src/main/java/java/security/cert/X509Certificate.java b/libcore/security/src/main/java/java/security/cert/X509Certificate.java
index 9e10077..e49901c 100644
--- a/libcore/security/src/main/java/java/security/cert/X509Certificate.java
+++ b/libcore/security/src/main/java/java/security/cert/X509Certificate.java
@@ -33,7 +33,6 @@
* <p>
* This represents a standard way for accessing the attributes of X.509
* certificates.
- * </p>
* <p>
* The basic X.509 v3 format described in ASN.1:
*
@@ -59,16 +58,12 @@
* -- If present, version must be v3
* }
* </pre>
- * </p>
* <p>
* For more information consult RFC 2459
* "Internet X.509 Public Key Infrastructure Certificate and CRL Profile" at <a
* href
* ="http://www.ietf.org/rfc/rfc2459.txt">http://www.ietf.org/rfc/rfc2459.txt
* </a> .
- * </p>
- *
- * @since Android 1.0
*/
public abstract class X509Certificate
extends Certificate implements X509Extension {
@@ -77,8 +72,6 @@
/**
* Creates a new {@code X509Certificate}.
- *
- * @since Android 1.0
*/
protected X509Certificate() {
super("X.509"); //$NON-NLS-1$
@@ -101,13 +94,10 @@
* generalTime GeneralizedTime }
* </pre>
*
- * </p>
- *
* @throws CertificateExpiredException
* if the certificate has expired.
* @throws CertificateNotYetValidException
* if the certificate is not yet valid.
- * @since Android 1.0
*/
public abstract void checkValidity()
throws CertificateExpiredException, CertificateNotYetValidException;
@@ -122,7 +112,6 @@
* @throws CertificateNotYetValidException
* if the certificate is not yet valid.
* @see #checkValidity()
- * @since Android 1.0
*/
public abstract void checkValidity(Date date)
throws CertificateExpiredException, CertificateNotYetValidException;
@@ -136,10 +125,7 @@
* Version ::= INTEGER { v1(0), v2(1), v3(2) }
* </pre>
*
- * </p>
- *
* @return the version number.
- * @since Android 1.0
*/
public abstract int getVersion();
@@ -152,10 +138,7 @@
* CertificateSerialNumber ::= INTEGER
* </pre>
*
- * </p>
- *
* @return the serial number.
- * @since Android 1.0
*/
public abstract BigInteger getSerialNumber();
@@ -184,12 +167,10 @@
* AttributeValue ::= ANY DEFINED BY AttributeType
* </pre>
*
- * </p>
* <b>replaced by:</b> {@link #getIssuerX500Principal()}.
*
* @return the {@code issuer} as an implementation specific {@code
* Principal}.
- * @since Android 1.0
*/
public abstract Principal getIssuerDN() ;
@@ -198,7 +179,6 @@
* X500Principal}.
*
* @return the {@code issuer} (issuer distinguished name).
- * @since Android 1.0
*/
public X500Principal getIssuerX500Principal() {
@@ -243,13 +223,10 @@
* AttributeValue ::= ANY DEFINED BY AttributeType
* </pre>
*
- * </p>
* <p>
* <b>replaced by:</b> {@link #getSubjectX500Principal()}.
- * </p>
- *
+ *
* @return the {@code subject} (subject distinguished name).
- * @since Android 1.0
*/
public abstract Principal getSubjectDN();
@@ -258,7 +235,6 @@
* X500Principal}.
*
* @return the {@code subject} (subject distinguished name)
- * @since Android 1.0
*/
public X500Principal getSubjectX500Principal() {
@@ -283,7 +259,6 @@
* certificate.
*
* @return the start of the validity period.
- * @since Android 1.0
*/
public abstract Date getNotBefore();
@@ -292,7 +267,6 @@
* certificate.
*
* @return the end of the validity period.
- * @since Android 1.0
*/
public abstract Date getNotAfter();
@@ -303,7 +277,6 @@
* @return the DER-encoded certificate information.
* @throws CertificateEncodingException
* if an error occurs in encoding
- * @since Android 1.0
*/
public abstract byte[] getTBSCertificate()
throws CertificateEncodingException;
@@ -312,7 +285,6 @@
* Returns the raw signature bits from the certificate.
*
* @return the raw signature bits from the certificate.
- * @since Android 1.0
*/
public abstract byte[] getSignature();
@@ -320,7 +292,6 @@
* Returns the name of the algorithm for the certificate signature.
*
* @return the signature algorithm name.
- * @since Android 1.0
*/
public abstract String getSigAlgName();
@@ -328,7 +299,6 @@
* Returns the OID of the signature algorithm from the certificate.
*
* @return the OID of the signature algorithm.
- * @since Android 1.0
*/
public abstract String getSigAlgOID();
@@ -337,7 +307,6 @@
*
* @return the parameters of the signature algorithm, or {@code null} if
* none are used.
- * @since Android 1.0
*/
public abstract byte[] getSigAlgParams();
@@ -346,7 +315,6 @@
*
* @return the {@code issuerUniqueID} or {@code null} if there's none in the
* certificate.
- * @since Android 1.0
*/
public abstract boolean[] getIssuerUniqueID();
@@ -355,7 +323,6 @@
*
* @return the {@code subjectUniqueID} or null if there's none in the
* certificate.
- * @since Android 1.0
*/
public abstract boolean[] getSubjectUniqueID();
@@ -378,11 +345,8 @@
*
* </pre>
*
- * </p>
- *
* @return the {@code KeyUsage} extension or {@code null} if there's none in
* the certificate.
- * @since Android 1.0
*/
public abstract boolean[] getKeyUsage();
@@ -394,7 +358,6 @@
* in the certificate.
* @throws CertificateParsingException
* if the extension decoding fails.
- * @since Android 1.0
*/
public List<String> getExtendedKeyUsage()
throws CertificateParsingException {
@@ -408,7 +371,6 @@
* @return the path length of the certificate constraints if the extension
* is present or {@code -1} if the extension is not present. {@code
* Integer.MAX_VALUE} if there's not limit.
- * @since Android 1.0
*/
public abstract int getBasicConstraints();
@@ -436,13 +398,10 @@
*
* </pre>
*
- * </p>
- *
* @return the subject alternative names or {@code null} if there are none
* in the certificate.
* @throws CertificateParsingException
* if decoding of the extension fails.
- * @since Android 1.0
*/
public Collection<List<?>> getSubjectAlternativeNames()
throws CertificateParsingException {
@@ -473,13 +432,10 @@
*
* </pre>
*
- * </p>
- *
* @return the issuer alternative names of {@code null} if there are none in
* the certificate.
* @throws CertificateParsingException
* if decoding of the extension fails.
- * @since Android 1.0
*/
public Collection<List<?>> getIssuerAlternativeNames()
throws CertificateParsingException {
diff --git a/libcore/security/src/main/java/java/security/cert/X509Extension.java b/libcore/security/src/main/java/java/security/cert/X509Extension.java
index cc8648b..1543f3d 100644
--- a/libcore/security/src/main/java/java/security/cert/X509Extension.java
+++ b/libcore/security/src/main/java/java/security/cert/X509Extension.java
@@ -21,8 +21,6 @@
/**
* The interface specifying an X.509 Certificate or CRL extension.
- *
- * @since Android 1.0
*/
public interface X509Extension {
@@ -33,7 +31,6 @@
* @return the set of extension OIDs marked as CRITIAL, an empty set if none
* are marked as CRITICAL, or {@code null} if no extensions are
* present.
- * @since Android 1.0
*/
public Set<String> getCriticalExtensionOIDs();
@@ -45,7 +42,6 @@
* the object identifier to get the extension value for.
* @return the extension value as DER-encoded OCTET string, or {@code null}
* if no extension for the specified OID can be found.
- * @since Android 1.0
*/
public byte[] getExtensionValue(String oid);
@@ -56,7 +52,6 @@
* @return the set of extension OIDs marked as NON-CRITIAL, an empty set if
* none are marked as NON-.CRITICAL, or {@code null} if no
* extensions are present.
- * @since Android 1.0
*/
public Set<String> getNonCriticalExtensionOIDs();
@@ -66,7 +61,6 @@
*
* @return {@code true} if an unsupported CRITICAL extension is present,
* {@code false} otherwise.
- * @since Android 1.0
*/
public boolean hasUnsupportedCriticalExtension();
}
diff --git a/libcore/security/src/main/java/java/security/interfaces/DSAKey.java b/libcore/security/src/main/java/java/security/interfaces/DSAKey.java
index 1362bff..ac9aade 100644
--- a/libcore/security/src/main/java/java/security/interfaces/DSAKey.java
+++ b/libcore/security/src/main/java/java/security/interfaces/DSAKey.java
@@ -21,8 +21,6 @@
/**
* The base interface for Digital Signature Algorithm (DSA) public or private
* keys.
- *
- * @since Android 1.0
*/
public interface DSAKey {
@@ -30,8 +28,7 @@
* Returns the DSA key parameters.
*
* @return the DSA key parameters.
- * @since Android 1.0
*/
public DSAParams getParams();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/interfaces/DSAKeyPairGenerator.java b/libcore/security/src/main/java/java/security/interfaces/DSAKeyPairGenerator.java
index 4b89c6a..b7b5480 100644
--- a/libcore/security/src/main/java/java/security/interfaces/DSAKeyPairGenerator.java
+++ b/libcore/security/src/main/java/java/security/interfaces/DSAKeyPairGenerator.java
@@ -22,8 +22,6 @@
/**
* The interface for key generators that can generate DSA key pairs.
- *
- * @since Android 1.0
*/
public interface DSAKeyPairGenerator {
@@ -38,7 +36,6 @@
* @throws InvalidParameterException
* if the specified parameter values are {@code null} or
* invalid.
- * @since Android 1.0
*/
public void initialize(DSAParams params, SecureRandom random)
throws InvalidParameterException;
@@ -53,7 +50,6 @@
* it will use the pre-calculated values for the specified modulus
* length. Default parameters are available for modulus lengths of 512 and 1024
* bits.
- * </p>
*
* @param modlen
* the length of the modulus in bits.
@@ -65,8 +61,7 @@
* if the specified modulus length is not valid, or if there are
* no pre-calculated values and {@code genParams} is {@code
* false}.
- * @since Android 1.0
*/
public void initialize(int modlen, boolean genParams, SecureRandom random)
throws InvalidParameterException;
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/interfaces/DSAParams.java b/libcore/security/src/main/java/java/security/interfaces/DSAParams.java
index 0483da2..62f2d00 100644
--- a/libcore/security/src/main/java/java/security/interfaces/DSAParams.java
+++ b/libcore/security/src/main/java/java/security/interfaces/DSAParams.java
@@ -21,8 +21,6 @@
/**
* The interface for Digital Signature Algorithm (DSA) specific parameters.
- *
- * @since Android 1.0
*/
public interface DSAParams {
@@ -30,7 +28,6 @@
* Returns the base ({@code g}) value.
*
* @return the base ({@code g}) value.
- * @since Android 1.0
*/
public BigInteger getG();
@@ -38,7 +35,6 @@
* Returns the prime ({@code p}) value.
*
* @return the prime ({@code p}) value.
- * @since Android 1.0
*/
public BigInteger getP();
@@ -46,7 +42,6 @@
* Returns the subprime ({@code q} value.
*
* @return the subprime ({@code q} value.
- * @since Android 1.0
*/
public BigInteger getQ();
diff --git a/libcore/security/src/main/java/java/security/interfaces/DSAPrivateKey.java b/libcore/security/src/main/java/java/security/interfaces/DSAPrivateKey.java
index e2592ca..6419440 100644
--- a/libcore/security/src/main/java/java/security/interfaces/DSAPrivateKey.java
+++ b/libcore/security/src/main/java/java/security/interfaces/DSAPrivateKey.java
@@ -22,15 +22,11 @@
/**
* The interface for a Digital Signature Algorithm (DSA) private key.
- *
- * @since Android 1.0
*/
public interface DSAPrivateKey extends DSAKey, PrivateKey {
/**
* The serial version identifier.
- *
- * @since Android 1.0
*/
public static final long serialVersionUID = 7776497482533790279L;
@@ -38,8 +34,7 @@
* Returns the private key value {@code x}.
*
* @return the private key value {@code x}.
- * @since Android 1.0
*/
public BigInteger getX();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/interfaces/DSAPublicKey.java b/libcore/security/src/main/java/java/security/interfaces/DSAPublicKey.java
index ccb985e..9642bf1 100644
--- a/libcore/security/src/main/java/java/security/interfaces/DSAPublicKey.java
+++ b/libcore/security/src/main/java/java/security/interfaces/DSAPublicKey.java
@@ -22,15 +22,11 @@
/**
* The interface for a Digital Signature Algorithm (DSA) public key.
- *
- * @since Android 1.0
*/
public interface DSAPublicKey extends DSAKey, PublicKey {
/**
* The serial version identifier.
- *
- * @since Android 1.0
*/
public static final long serialVersionUID = 1234526332779022332L;
@@ -38,8 +34,7 @@
* Returns the public key value {@code y}.
*
* @return the public key value {@code y}.
- * @since Android 1.0
*/
public BigInteger getY();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/interfaces/ECKey.java b/libcore/security/src/main/java/java/security/interfaces/ECKey.java
index 9f5d254..5469392 100644
--- a/libcore/security/src/main/java/java/security/interfaces/ECKey.java
+++ b/libcore/security/src/main/java/java/security/interfaces/ECKey.java
@@ -21,8 +21,6 @@
/**
* The base interface for Elliptic Curve (EC) public or private keys.
- *
- * @since Android 1.0
*/
public interface ECKey {
@@ -30,7 +28,6 @@
* Returns the EC key parameters.
*
* @return the EC key parameters.
- * @since Android 1.0
*/
public ECParameterSpec getParams();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/interfaces/ECPrivateKey.java b/libcore/security/src/main/java/java/security/interfaces/ECPrivateKey.java
index 74ef4c2..254d2a6 100644
--- a/libcore/security/src/main/java/java/security/interfaces/ECPrivateKey.java
+++ b/libcore/security/src/main/java/java/security/interfaces/ECPrivateKey.java
@@ -22,15 +22,11 @@
/**
* The interface for an Elliptic Curve (EC) private key.
- *
- * @since Android 1.0
*/
public interface ECPrivateKey extends PrivateKey, ECKey {
/**
* The serial version identifier.
- *
- * @since Android 1.0
*/
public static final long serialVersionUID = -7896394956925609184L;
@@ -38,7 +34,6 @@
* Returns the private value {@code S}.
*
* @return the private value {@code S}.
- * @since Android 1.0
*/
public BigInteger getS();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/interfaces/ECPublicKey.java b/libcore/security/src/main/java/java/security/interfaces/ECPublicKey.java
index 063dfe9..8ad97fc 100644
--- a/libcore/security/src/main/java/java/security/interfaces/ECPublicKey.java
+++ b/libcore/security/src/main/java/java/security/interfaces/ECPublicKey.java
@@ -22,15 +22,11 @@
/**
* The interface for an Elliptic Curve (EC) public key.
- *
- * @since Android 1.0
*/
public interface ECPublicKey extends PublicKey, ECKey {
/**
* The serial version identifier.
- *
- * @since Android 1.0
*/
public static final long serialVersionUID = -3314988629879632826L;
@@ -38,7 +34,6 @@
* Returns the public point {@code W} on an elliptic curve (EC).
*
* @return the public point {@code W} on an elliptic curve (EC).
- * @since Android 1.0
*/
public ECPoint getW();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/interfaces/RSAKey.java b/libcore/security/src/main/java/java/security/interfaces/RSAKey.java
index bc0877e..2c9e6c1 100644
--- a/libcore/security/src/main/java/java/security/interfaces/RSAKey.java
+++ b/libcore/security/src/main/java/java/security/interfaces/RSAKey.java
@@ -21,8 +21,6 @@
/**
* The base interface for PKCS#1 RSA public and private keys.
- *
- * @since Android 1.0
*/
public interface RSAKey {
@@ -30,7 +28,6 @@
* Returns the modulus.
*
* @return the modulus.
- * @since Android 1.0
*/
public BigInteger getModulus();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java b/libcore/security/src/main/java/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java
index c5e86c3..d8aa1bf 100644
--- a/libcore/security/src/main/java/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java
+++ b/libcore/security/src/main/java/java/security/interfaces/RSAMultiPrimePrivateCrtKey.java
@@ -24,15 +24,11 @@
* The interface for a Multi-Prime RSA private key. Specified by <a
* href="http://www.rsa.com/rsalabs/node.asp?id=2125">PKCS #1 v2.0 Amendment 1:
* Multi-Prime RSA</a>.
- *
- * @since Android 1.0
*/
public interface RSAMultiPrimePrivateCrtKey extends RSAPrivateKey {
/**
* the serial version identifier.
- *
- * @since Android 1.0
*/
public static final long serialVersionUID = 618058533534628008L;
@@ -40,7 +36,6 @@
* Returns the CRT coefficient, {@code q^-1 mod p}.
*
* @return the CRT coefficient.
- * @since Android 1.0
*/
public BigInteger getCrtCoefficient();
@@ -49,7 +44,6 @@
*
* @return the information for the additional primes, or {@code null} if
* there are only the two primes ({@code p, q}),
- * @since Android 1.0
*/
public RSAOtherPrimeInfo[] getOtherPrimeInfo();
@@ -57,7 +51,6 @@
* Returns the prime factor {@code p} of {@code n}.
*
* @return the prime factor {@code p} of {@code n}.
- * @since Android 1.0
*/
public BigInteger getPrimeP();
@@ -65,7 +58,6 @@
* Returns the prime factor {@code q} of {@code n}.
*
* @return the prime factor {@code q} of {@code n}.
- * @since Android 1.0
*/
public BigInteger getPrimeQ();
@@ -73,7 +65,6 @@
* Returns the CRT exponent of the prime {@code p}.
*
* @return the CRT exponent of the prime {@code p}.
- * @since Android 1.0
*/
public BigInteger getPrimeExponentP();
@@ -81,7 +72,6 @@
* Returns the CRT exponent of the prime {@code q}.
*
* @return the CRT exponent of the prime {@code q}.
- * @since Android 1.0
*/
public BigInteger getPrimeExponentQ();
@@ -89,7 +79,6 @@
* Returns the public exponent {@code e}.
*
* @return the public exponent {@code e}.
- * @since Android 1.0
*/
public BigInteger getPublicExponent();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/interfaces/RSAPrivateCrtKey.java b/libcore/security/src/main/java/java/security/interfaces/RSAPrivateCrtKey.java
index 48d70ce..a670491 100644
--- a/libcore/security/src/main/java/java/security/interfaces/RSAPrivateCrtKey.java
+++ b/libcore/security/src/main/java/java/security/interfaces/RSAPrivateCrtKey.java
@@ -21,15 +21,11 @@
/**
* The interface for a PKCS#1 RSA private key using CRT information values.
- *
- * @since Android 1.0
*/
public interface RSAPrivateCrtKey extends RSAPrivateKey {
/**
* The serial version identifier.
- *
- * @since Android 1.0
*/
public static final long serialVersionUID = -5682214253527700368L;
@@ -37,7 +33,6 @@
* Returns the CRT coefficient, {@code q^-1 mod p}.
*
* @return the CRT coefficient.
- * @since Android 1.0
*/
public BigInteger getCrtCoefficient();
@@ -45,7 +40,6 @@
* Returns the prime factor {@code p} of {@code n}.
*
* @return the prime factor {@code p} of {@code n}.
- * @since Android 1.0
*/
public BigInteger getPrimeP();
@@ -53,7 +47,6 @@
* Returns the prime factor {@code q} of {@code n}.
*
* @return the prime factor {@code q} of {@code n}.
- * @since Android 1.0
*/
public BigInteger getPrimeQ();
@@ -61,7 +54,6 @@
* Returns the CRT exponent of the primet {@code p}.
*
* @return the CRT exponent of the prime {@code p}.
- * @since Android 1.0
*/
public BigInteger getPrimeExponentP();
@@ -69,7 +61,6 @@
* Returns the CRT exponent of the prime {@code q}.
*
* @return the CRT exponent of the prime {@code q}.
- * @since Android 1.0
*/
public BigInteger getPrimeExponentQ();
@@ -77,7 +68,6 @@
* Returns the public exponent {@code e}.
*
* @return the public exponent {@code e}.
- * @since Android 1.0
*/
public BigInteger getPublicExponent();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/interfaces/RSAPrivateKey.java b/libcore/security/src/main/java/java/security/interfaces/RSAPrivateKey.java
index 041a1e3..0da15e9 100644
--- a/libcore/security/src/main/java/java/security/interfaces/RSAPrivateKey.java
+++ b/libcore/security/src/main/java/java/security/interfaces/RSAPrivateKey.java
@@ -22,15 +22,11 @@
/**
* The interface for an PKCS#1 RSA private key.
- *
- * @since Android 1.0
*/
public interface RSAPrivateKey extends PrivateKey, RSAKey {
/**
* The serial version identifier.
- *
- * @since Android 1.0
*/
public static final long serialVersionUID = 5187144804936595022L;
@@ -38,7 +34,6 @@
* Returns the private exponent {@code d}.
*
* @return the private exponent {@code d}.
- * @since Android 1.0
*/
public BigInteger getPrivateExponent();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/interfaces/RSAPublicKey.java b/libcore/security/src/main/java/java/security/interfaces/RSAPublicKey.java
index b13b1aa..379351f 100644
--- a/libcore/security/src/main/java/java/security/interfaces/RSAPublicKey.java
+++ b/libcore/security/src/main/java/java/security/interfaces/RSAPublicKey.java
@@ -22,15 +22,11 @@
/**
* The interface for a PKCS#1 RSA public key.
- *
- * @since Android 1.0
*/
public interface RSAPublicKey extends PublicKey, RSAKey {
/**
* The serial version identifier.
- *
- * @since Android 1.0
*/
public static final long serialVersionUID = -8727434096241101194L;
@@ -38,8 +34,7 @@
* Returns the public exponent {@code e}.
*
* @return the public exponent {@code e}.
- * @since Android 1.0
*/
public BigInteger getPublicExponent();
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/spec/AlgorithmParameterSpec.java b/libcore/security/src/main/java/java/security/spec/AlgorithmParameterSpec.java
index 32c7a3a..0cbba76 100644
--- a/libcore/security/src/main/java/java/security/spec/AlgorithmParameterSpec.java
+++ b/libcore/security/src/main/java/java/security/spec/AlgorithmParameterSpec.java
@@ -20,8 +20,6 @@
/**
* The marker interface for algorithm parameter specifications. The purpose is
* to group parameter specifications for algorithms.
- *
- * @since Android 1.0
*/
public interface AlgorithmParameterSpec {
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/spec/DSAParameterSpec.java b/libcore/security/src/main/java/java/security/spec/DSAParameterSpec.java
index 5465b5b..e23a682 100644
--- a/libcore/security/src/main/java/java/security/spec/DSAParameterSpec.java
+++ b/libcore/security/src/main/java/java/security/spec/DSAParameterSpec.java
@@ -22,8 +22,6 @@
/**
* The parameter specification used with the Digital Signature Algorithm (DSA).
- *
- * @since Android 1.0
*/
public class DSAParameterSpec implements AlgorithmParameterSpec, DSAParams {
// Prime
@@ -43,7 +41,6 @@
* the sub-prime {@code q}.
* @param g
* the base {@code g};
- * @since Android 1.0
*/
public DSAParameterSpec(BigInteger p, BigInteger q, BigInteger g) {
this.p = p;
@@ -55,7 +52,6 @@
* Returns the base {@code g}.
*
* @return the base {@code g}.
- * @since Android 1.0
*/
public BigInteger getG() {
return g;
@@ -65,7 +61,6 @@
* Returns the prime {@code p}.
*
* @return the prime {@code p}.
- * @since Android 1.0
*/
public BigInteger getP() {
return p;
@@ -73,8 +68,8 @@
/**
* Returns the sub-prime {@code q}.
+ *
* @return the sub-prime {@code q}.
- * @since Android 1.0
*/
public BigInteger getQ() {
return q;
diff --git a/libcore/security/src/main/java/java/security/spec/DSAPrivateKeySpec.java b/libcore/security/src/main/java/java/security/spec/DSAPrivateKeySpec.java
index 3b692c8..6dc12c8 100644
--- a/libcore/security/src/main/java/java/security/spec/DSAPrivateKeySpec.java
+++ b/libcore/security/src/main/java/java/security/spec/DSAPrivateKeySpec.java
@@ -21,8 +21,6 @@
/**
* The parameters specifying a DSA private key.
- *
- * @since Android 1.0
*/
public class DSAPrivateKeySpec implements KeySpec {
// Private key
@@ -46,7 +44,6 @@
* the sub-prime {@code q}.
* @param g
* the base {@code g}.
- * @since Android 1.0
*/
public DSAPrivateKeySpec(BigInteger x, BigInteger p,
BigInteger q, BigInteger g) {
@@ -60,7 +57,6 @@
* Returns the base {@code g}.
*
* @return the base {@code g}.
- * @since Android 1.0
*/
public BigInteger getG() {
return g;
@@ -70,7 +66,6 @@
* Returns the prime {@code p}.
*
* @return the prime {@code p}.
- * @since Android 1.0
*/
public BigInteger getP() {
return p;
@@ -80,7 +75,6 @@
* Returns the sub-prime {@code q}.
*
* @return the sub-prime {@code q}.
- * @since Android 1.0
*/
public BigInteger getQ() {
return q;
@@ -90,7 +84,6 @@
* Returns the private key {@code x}.
*
* @return the private key {@code x}.
- * @since Android 1.0
*/
public BigInteger getX() {
return x;
diff --git a/libcore/security/src/main/java/java/security/spec/DSAPublicKeySpec.java b/libcore/security/src/main/java/java/security/spec/DSAPublicKeySpec.java
index 95d1141..af90919 100644
--- a/libcore/security/src/main/java/java/security/spec/DSAPublicKeySpec.java
+++ b/libcore/security/src/main/java/java/security/spec/DSAPublicKeySpec.java
@@ -21,8 +21,6 @@
/**
* The parameters specifying a DSA public key.
- *
- * @since Android 1.0
*/
public class DSAPublicKeySpec implements KeySpec {
// Public key
@@ -46,7 +44,6 @@
* the sub-prime {@code q}.
* @param g
* the base {@code g}.
- * @since Android 1.0
*/
public DSAPublicKeySpec(BigInteger y, BigInteger p,
BigInteger q, BigInteger g) {
@@ -60,7 +57,6 @@
* Returns the base {@code g}.
*
* @return the base {@code g}.
- * @since Android 1.0
*/
public BigInteger getG() {
return g;
@@ -70,7 +66,6 @@
* Returns the prime {@code p}.
*
* @return the prime {@code p}.
- * @since Android 1.0
*/
public BigInteger getP() {
return p;
@@ -80,7 +75,6 @@
* Returns the sub-prime {@code q}.
*
* @return the sub-prime {@code q}.
- * @since Android 1.0
*/
public BigInteger getQ() {
return q;
@@ -90,7 +84,6 @@
* Returns the public key value {@code y}.
*
* @return the public key value {@code y}.
- * @since Android 1.0
*/
public BigInteger getY() {
return y;
diff --git a/libcore/security/src/main/java/java/security/spec/ECField.java b/libcore/security/src/main/java/java/security/spec/ECField.java
index 74a5eb8..b4c6be2 100644
--- a/libcore/security/src/main/java/java/security/spec/ECField.java
+++ b/libcore/security/src/main/java/java/security/spec/ECField.java
@@ -19,8 +19,6 @@
/**
* The base interface for a Finite Field of an Elliptic Curve.
- *
- * @since Android 1.0
*/
public interface ECField {
@@ -28,7 +26,6 @@
* Returns the size of the field (in bits).
*
* @return the size of the field (in bits).
- * @since Android 1.0
*/
int getFieldSize();
}
diff --git a/libcore/security/src/main/java/java/security/spec/ECFieldF2m.java b/libcore/security/src/main/java/java/security/spec/ECFieldF2m.java
index d68378b..e5a636a 100644
--- a/libcore/security/src/main/java/java/security/spec/ECFieldF2m.java
+++ b/libcore/security/src/main/java/java/security/spec/ECFieldF2m.java
@@ -25,8 +25,6 @@
/**
* The parameters specifying a <i>characteristic 2 finite field</i> of an
* elliptic curve.
- *
- * @since Android 1.0
*/
public class ECFieldF2m implements ECField {
// Mid terms array length for trinomial basis
@@ -52,7 +50,6 @@
* the exponent {@code m} for the number of elements.
* @throws IllegalArgumentException
* if {@code m <= zero}.
- * @since Android 1.0
*/
public ECFieldF2m(int m) {
this.m = m;
@@ -69,8 +66,7 @@
* <p>
* The reduction polynomial must be either <i>trinomial</i> or
* <i>pentanomial</i>.
- * </p>
- *
+ *
* @param m
* the exponent {@code m} for the number of elements.
* @param rp
@@ -79,7 +75,6 @@
* polynomial.
* @throws IllegalArgumentException
* if {@code m <= zero} or the {@code rp} is invalid.
- * @since Android 1.0
*/
public ECFieldF2m(int m, BigInteger rp) {
this.m = m;
@@ -117,7 +112,6 @@
* <p>
* The reduction polynomial must be either <i>trinomial</i> or
* <i>pentanomial</i>.
- * </p>
*
* @param m
* the exponent {@code m} for the number of elements.
@@ -127,7 +121,6 @@
* @throws IllegalArgumentException
* if {@code m <= zero} or the reduction polynomial is not
* valid.
- * @since Android 1.0
*/
public ECFieldF2m(int m, int[] ks) {
this.m = m;
@@ -182,7 +175,6 @@
* the object to compare to this finite field.
* @return {@code true} if the specified object is equal to this finite field,
* otherwise {@code false}.
- * @since Android 1.0
*/
public boolean equals(Object obj) {
// object equals to itself
@@ -214,7 +206,6 @@
* Returns the size of this finite field (in bits).
*
* @return the size of this finite field (in bits).
- * @since Android 1.0
*/
public int getFieldSize() {
return m;
@@ -225,7 +216,6 @@
* the number of elements.
*
* @return the exponent {@code m} for this finite field
- * @since Android 1.0
*/
public int getM() {
return m;
@@ -238,7 +228,6 @@
* @return a copy of the integer array containing the order of the middle
* term(s) of the reduction polynomial for a polynomial basis or
* {@code null} for a normal basis.
- * @since Android 1.0
*/
public int[] getMidTermsOfReductionPolynomial() {
// Defensively copies private array
@@ -261,7 +250,6 @@
* @return the base of the reduction polynomial with the n-th bit
* corresponding to the n-th coefficient of the reduction polynomial
* for a polynomial basis or {@code null} for a normal basis.
- * @since Android 1.0
*/
public BigInteger getReductionPolynomial() {
return rp;
@@ -271,7 +259,6 @@
* Returns the hashcode value for this finite field.
*
* @return the hashcode value for this finite field.
- * @since Android 1.0
*/
public int hashCode() {
return rp == null ? m : m + rp.hashCode();
diff --git a/libcore/security/src/main/java/java/security/spec/ECFieldFp.java b/libcore/security/src/main/java/java/security/spec/ECFieldFp.java
index d3f4ee6..b68238d 100644
--- a/libcore/security/src/main/java/java/security/spec/ECFieldFp.java
+++ b/libcore/security/src/main/java/java/security/spec/ECFieldFp.java
@@ -24,8 +24,6 @@
/**
* The parameters specifying a <i>prime finite field</i> of an
* elliptic curve.
- *
- * @since Android 1.0
*/
public class ECFieldFp implements ECField {
// Prime
@@ -39,7 +37,6 @@
* the prime value {@code p}.
* @throws IllegalArgumentException
* if {@code p <= zero}.
- * @since Android 1.0
*/
public ECFieldFp(BigInteger p) {
this.p = p;
@@ -56,7 +53,6 @@
* Returns the size of the finite field (in bits).
*
* @return the size of the finite field (in bits).
- * @since Android 1.0
*/
public int getFieldSize() {
return p.bitLength();
@@ -66,7 +62,6 @@
* Returns the prime value {@code p} for this finite field.
*
* @return the prime value {@code p} for this finite field.
- * @since Android 1.0
*/
public BigInteger getP() {
return p;
@@ -79,7 +74,6 @@
* the object to compare to this finite field.
* @return {@code true} if the specified object is equal to this finite field,
* otherwise {@code false}.
- * @since Android 1.0
*/
public boolean equals(Object obj) {
// object equals itself
@@ -96,7 +90,6 @@
* Returns the hashcode value for this finite field.
*
* @return the hashcode value for this finite field.
- * @since Android 1.0
*/
public int hashCode() {
return p.hashCode();
diff --git a/libcore/security/src/main/java/java/security/spec/ECGenParameterSpec.java b/libcore/security/src/main/java/java/security/spec/ECGenParameterSpec.java
index 210b315..de4cd04 100644
--- a/libcore/security/src/main/java/java/security/spec/ECGenParameterSpec.java
+++ b/libcore/security/src/main/java/java/security/spec/ECGenParameterSpec.java
@@ -21,8 +21,6 @@
/**
* The parameter specification used to generate elliptic curve domain parameters.
- *
- * @since Android 1.0
*/
public class ECGenParameterSpec implements AlgorithmParameterSpec {
// Standard (or predefined) name for EC domain
@@ -35,7 +33,6 @@
*
* @param name
* the name of the elliptic curve domain parameter.
- * @since Android 1.0
*/
public ECGenParameterSpec(String name) {
this.name = name;
@@ -49,7 +46,6 @@
* curve domain parameter.
*
* @return the name
- * @since Android 1.0
*/
public String getName() {
return name;
diff --git a/libcore/security/src/main/java/java/security/spec/ECParameterSpec.java b/libcore/security/src/main/java/java/security/spec/ECParameterSpec.java
index e10757b..a1985db 100644
--- a/libcore/security/src/main/java/java/security/spec/ECParameterSpec.java
+++ b/libcore/security/src/main/java/java/security/spec/ECParameterSpec.java
@@ -23,8 +23,6 @@
/**
* The parameter specification used with Elliptic Curve Cryptography (ECC).
- *
- * @since Android 1.0
*/
public class ECParameterSpec implements AlgorithmParameterSpec {
// Elliptic curve for which this is parameter
@@ -51,7 +49,6 @@
* the co-factor.
* @throws IllegalArgumentException
* if {@code order <= zero} or {@code cofactor <= zero}.
- * @since Android 1.0
*/
public ECParameterSpec(EllipticCurve curve, ECPoint generator,
BigInteger order, int cofactor) {
@@ -84,7 +81,6 @@
* Returns the {@code cofactor}.
*
* @return the {@code cofactor}.
- * @since Android 1.0
*/
public int getCofactor() {
return cofactor;
@@ -94,7 +90,6 @@
* Returns the elliptic curve.
*
* @return the elliptic curve.
- * @since Android 1.0
*/
public EllipticCurve getCurve() {
return curve;
@@ -104,7 +99,6 @@
* Returns the generator (or base point).
*
* @return the generator (or base point).
- * @since Android 1.0
*/
public ECPoint getGenerator() {
return generator;
@@ -114,7 +108,6 @@
* Returns the order of the generator.
*
* @return the order of the generator.
- * @since Android 1.0
*/
public BigInteger getOrder() {
return order;
diff --git a/libcore/security/src/main/java/java/security/spec/ECPoint.java b/libcore/security/src/main/java/java/security/spec/ECPoint.java
index 3aba6c7..0751757 100644
--- a/libcore/security/src/main/java/java/security/spec/ECPoint.java
+++ b/libcore/security/src/main/java/java/security/spec/ECPoint.java
@@ -23,15 +23,11 @@
/**
* A Point on an Elliptic Curve in barycentric (or affine) coordinates.
- *
- * @since Android 1.0
*/
public class ECPoint {
/**
* The point on an Elliptic Curve at infinity.
- *
- * @since Android 1.0
*/
public static final ECPoint POINT_INFINITY = new ECPoint();
// affine X coordinate of this point
@@ -52,7 +48,6 @@
* the x-coordinate.
* @param affineY
* the y-coordinate.
- * @since Android 1.0
*/
public ECPoint(BigInteger affineX, BigInteger affineY) {
this.affineX = affineX;
@@ -69,7 +64,6 @@
* Returns the x-coordinate.
*
* @return the x-coordinate, or {@code null} for the infinite point.
- * @since Android 1.0
*/
public BigInteger getAffineX() {
return affineX;
@@ -79,7 +73,6 @@
* Returns the y-coordinate.
*
* @return the y-coordinate, or {@code null} fot the infinite point.
- * @since Android 1.0
*/
public BigInteger getAffineY() {
return affineY;
@@ -93,7 +86,6 @@
* the object to compare.
* @return {@code true} if the specified object and this elliptic curve
* point are equal, otherwise {@code false}.
- * @since Android 1.0
*/
public boolean equals(Object other) {
if (this == other) {
@@ -116,7 +108,6 @@
* Returns the hashcode of this elliptic curve point.
*
* @return the hashcode of this elliptic curve point.
- * @since Android 1.0
*/
public int hashCode() {
if (this.affineX != null) {
diff --git a/libcore/security/src/main/java/java/security/spec/ECPrivateKeySpec.java b/libcore/security/src/main/java/java/security/spec/ECPrivateKeySpec.java
index de778fd..1ddfec3 100644
--- a/libcore/security/src/main/java/java/security/spec/ECPrivateKeySpec.java
+++ b/libcore/security/src/main/java/java/security/spec/ECPrivateKeySpec.java
@@ -23,8 +23,6 @@
/**
* The parameters specifying an Elliptic Curve (EC) private key.
- *
- * @since Android 1.0
*/
public class ECPrivateKeySpec implements KeySpec {
// Private value associated with this key
@@ -40,7 +38,6 @@
* the private value {@code S}.
* @param params
* the domain parameter specification.
- * @since Android 1.0
*/
public ECPrivateKeySpec(BigInteger s, ECParameterSpec params) {
this.s = s;
@@ -58,7 +55,6 @@
* Returns the domain parameter specification.
*
* @return the domain parameter specification.
- * @since Android 1.0
*/
public ECParameterSpec getParams() {
return params;
@@ -68,7 +64,6 @@
* Returns the private value {@code S}.
*
* @return the private value {@code S}.
- * @since Android 1.0
*/
public BigInteger getS() {
return s;
diff --git a/libcore/security/src/main/java/java/security/spec/ECPublicKeySpec.java b/libcore/security/src/main/java/java/security/spec/ECPublicKeySpec.java
index da182b5..0c88590 100644
--- a/libcore/security/src/main/java/java/security/spec/ECPublicKeySpec.java
+++ b/libcore/security/src/main/java/java/security/spec/ECPublicKeySpec.java
@@ -21,8 +21,6 @@
/**
* The parameters specifying an Elliptic Curve (EC) public key.
- *
- * @since Android 1.0
*/
public class ECPublicKeySpec implements KeySpec {
// The public point
@@ -40,7 +38,6 @@
* the domain parameter specification.
* @throws IllegalArgumentException
* if the specified point {@code W} is at infinity.
- * @since Android 1.0
*/
public ECPublicKeySpec(ECPoint w, ECParameterSpec params) {
this.w = w;
@@ -63,7 +60,6 @@
* Returns the domain parameter specification.
*
* @return the domain parameter specification.
- * @since Android 1.0
*/
public ECParameterSpec getParams() {
return params;
@@ -73,7 +69,6 @@
* Returns the public elliptic curve point {@code W}.
*
* @return the public elliptic curve point {@code W}.
- * @since Android 1.0
*/
public ECPoint getW() {
return w;
diff --git a/libcore/security/src/main/java/java/security/spec/EllipticCurve.java b/libcore/security/src/main/java/java/security/spec/EllipticCurve.java
index 3ab2921..45ff042 100644
--- a/libcore/security/src/main/java/java/security/spec/EllipticCurve.java
+++ b/libcore/security/src/main/java/java/security/spec/EllipticCurve.java
@@ -24,8 +24,6 @@
/**
* An Elliptic Curve with its necessary values.
- *
- * @since Android 1.0
*/
public class EllipticCurve {
@@ -59,7 +57,6 @@
* the seed used for the generation of the curve.
* @throws IllegalArgumentException
* if the specified coefficients are not in the specified field.
- * @since Android 1.0
*/
public EllipticCurve(ECField field, BigInteger a, BigInteger b, byte[] seed) {
this.field = field;
@@ -115,7 +112,6 @@
* the coefficient {@code b}.
* @throws IllegalArgumentException
* if the specified coefficients are not in the specified field.
- * @since Android 1.0
*/
public EllipticCurve(ECField field, BigInteger a, BigInteger b) {
this(field, a, b, null);
@@ -125,7 +121,6 @@
* Returns the coefficient {@code a} of this elliptic curve.
*
* @return the coefficient {@code a} of this elliptic curve.
- * @since Android 1.0
*/
public BigInteger getA() {
return a;
@@ -135,7 +130,6 @@
* Returns the coefficient {@code b} of this elliptic curve.
*
* @return the coefficient {@code b} of this elliptic curve.
- * @since Android 1.0
*/
public BigInteger getB() {
return b;
@@ -145,7 +139,6 @@
* Returns the finite field of this elliptic curve.
*
* @return the finite field of this elliptic curve.
- * @since Android 1.0
*/
public ECField getField() {
return field;
@@ -156,7 +149,6 @@
*
* @return a copy of the seed that was used to generate this elliptic curve,
* or {@code null} if none specified.
- * @since Android 1.0
*/
public byte[] getSeed() {
if (seed == null) {
@@ -176,7 +168,6 @@
* the object to compare.
* @return {@code true} if the specified object is equal to this elliptic
* curve, otherwise {@code false}.
- * @since Android 1.0
*/
public boolean equals(Object other) {
if (this == other) {
@@ -195,7 +186,6 @@
* Returns the hashcode of this elliptic curve.
*
* @return the hashcode of this elliptic curve.
- * @since Android 1.0
*/
public int hashCode() {
// hash init is delayed
diff --git a/libcore/security/src/main/java/java/security/spec/EncodedKeySpec.java b/libcore/security/src/main/java/java/security/spec/EncodedKeySpec.java
index f199bca..d34794c 100644
--- a/libcore/security/src/main/java/java/security/spec/EncodedKeySpec.java
+++ b/libcore/security/src/main/java/java/security/spec/EncodedKeySpec.java
@@ -20,8 +20,6 @@
/**
* The abstract key specification for a public or a private key in encoded
* format.
- *
- * @since Android 1.0
*/
public abstract class EncodedKeySpec implements KeySpec {
// Encoded key
@@ -32,7 +30,6 @@
*
* @param encodedKey
* the encoded key bytes.
- * @since Android 1.0
*/
public EncodedKeySpec(byte[] encodedKey) {
// Defensively copies parameter
@@ -46,7 +43,6 @@
* Returns the encoded key bytes.
*
* @return the encoded key bytes.
- * @since Android 1.0
*/
public byte[] getEncoded() {
// Defensively copies private array
@@ -62,7 +58,6 @@
*
* @return the name of the encoding format of this encoded key
* specification.
- * @since Android 1.0
*/
public abstract String getFormat();
}
diff --git a/libcore/security/src/main/java/java/security/spec/InvalidKeySpecException.java b/libcore/security/src/main/java/java/security/spec/InvalidKeySpecException.java
index a83e984..4ae5877 100644
--- a/libcore/security/src/main/java/java/security/spec/InvalidKeySpecException.java
+++ b/libcore/security/src/main/java/java/security/spec/InvalidKeySpecException.java
@@ -22,15 +22,11 @@
/**
* The exception that is thrown when an invalid key specification is
* encountered.
- *
- * @since Android 1.0
*/
public class InvalidKeySpecException extends GeneralSecurityException {
/**
* The serial version identifier.
- *
- * @since Android 1.0
*/
private static final long serialVersionUID = 3546139293998810778L;
@@ -39,7 +35,6 @@
*
* @param msg
* the detail message of this exception.
- * @since Android 1.0
*/
public InvalidKeySpecException(String msg) {
super(msg);
@@ -47,8 +42,6 @@
/**
* Creates a new {@code InvalidKeySpecException}.
- *
- * @since Android 1.0
*/
public InvalidKeySpecException() {
}
@@ -61,7 +54,6 @@
* the detail message of this exception.
* @param cause
* the cause of this exception.
- * @since Android 1.0
*/
public InvalidKeySpecException(String message, Throwable cause) {
super(message, cause);
@@ -72,7 +64,6 @@
*
* @param cause
* the cause of this exception.
- * @since Android 1.0
*/
public InvalidKeySpecException(Throwable cause) {
super(cause);
diff --git a/libcore/security/src/main/java/java/security/spec/InvalidParameterSpecException.java b/libcore/security/src/main/java/java/security/spec/InvalidParameterSpecException.java
index 668fda5..e308dd8 100644
--- a/libcore/security/src/main/java/java/security/spec/InvalidParameterSpecException.java
+++ b/libcore/security/src/main/java/java/security/spec/InvalidParameterSpecException.java
@@ -22,15 +22,11 @@
/**
* The exception that is thrown when an invalid parameter specification is
* encountered.
- *
- * @since Android 1.0
*/
public class InvalidParameterSpecException extends GeneralSecurityException {
/**
* The serial version identifier.
- *
- * @since Android 1.0
*/
private static final long serialVersionUID = -970468769593399342L;
@@ -40,7 +36,6 @@
*
* @param msg
* the detail message for this exception.
- * @since Android 1.0
*/
public InvalidParameterSpecException(String msg) {
super(msg);
@@ -48,9 +43,7 @@
/**
* Creates a new {@code InvalidParameterSpecException}.
- *
- * @since Android 1.0
*/
public InvalidParameterSpecException() {
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/spec/KeySpec.java b/libcore/security/src/main/java/java/security/spec/KeySpec.java
index 350a7eb..fe8df1d 100644
--- a/libcore/security/src/main/java/java/security/spec/KeySpec.java
+++ b/libcore/security/src/main/java/java/security/spec/KeySpec.java
@@ -20,8 +20,6 @@
/**
* The marker interface for key specifications. The purpose is
* to group key specifications for cryptographic keys.
- *
- * @since Android 1.0
*/
public interface KeySpec {
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/java/security/spec/MGF1ParameterSpec.java b/libcore/security/src/main/java/java/security/spec/MGF1ParameterSpec.java
index a40f0b3..6475d90 100644
--- a/libcore/security/src/main/java/java/security/spec/MGF1ParameterSpec.java
+++ b/libcore/security/src/main/java/java/security/spec/MGF1ParameterSpec.java
@@ -26,17 +26,12 @@
* Defined in the <a
* href="http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-1.html">PKCS #1 v2.1</a>
* standard
- * </p>
- *
- * @since Android 1.0
*/
public class MGF1ParameterSpec implements AlgorithmParameterSpec {
/**
* The predefined MGF1 parameter specification with an "SHA-1" message
* digest.
- *
- * @since Android 1.0
*/
public static final MGF1ParameterSpec SHA1 =
new MGF1ParameterSpec("SHA-1"); //$NON-NLS-1$
@@ -44,8 +39,6 @@
/**
* The predefined MGF1 parameter specification with an "SHA-256" message
* digest.
- *
- * @since Android 1.0
*/
public static final MGF1ParameterSpec SHA256 =
new MGF1ParameterSpec("SHA-256"); //$NON-NLS-1$
@@ -53,8 +46,6 @@
/**
* The predefined MGF1 parameter specification with an "SHA-384" message
* digest.
- *
- * @since Android 1.0
*/
public static final MGF1ParameterSpec SHA384 =
new MGF1ParameterSpec("SHA-384"); //$NON-NLS-1$
@@ -62,8 +53,6 @@
/**
* The predefined MGF1 parameter specification with an "SHA-512" message
* digest.
- *
- * @since Android 1.0
*/
public static final MGF1ParameterSpec SHA512 =
new MGF1ParameterSpec("SHA-512"); //$NON-NLS-1$
@@ -77,7 +66,6 @@
*
* @param mdName
* the name of the message digest algorithm.
- * @since Android 1.0
*/
public MGF1ParameterSpec(String mdName) {
this.mdName = mdName;
@@ -90,7 +78,6 @@
* Returns the name of the message digest algorithm.
*
* @return the name of the message digest algorithm.
- * @since Android 1.0
*/
public String getDigestAlgorithm() {
return mdName;
diff --git a/libcore/security/src/main/java/java/security/spec/PKCS8EncodedKeySpec.java b/libcore/security/src/main/java/java/security/spec/PKCS8EncodedKeySpec.java
index 5cb67b8..6910789 100644
--- a/libcore/security/src/main/java/java/security/spec/PKCS8EncodedKeySpec.java
+++ b/libcore/security/src/main/java/java/security/spec/PKCS8EncodedKeySpec.java
@@ -20,8 +20,6 @@
/**
* The key specification for an encoded private key in ASN.1 format as defined
* in the PKCS#8 standard.
- *
- * @since Android 1.0
*/
public class PKCS8EncodedKeySpec extends EncodedKeySpec {
@@ -31,7 +29,6 @@
*
* @param encodedKey
* the encoded key bytes.
- * @since Android 1.0
*/
public PKCS8EncodedKeySpec(byte[] encodedKey) {
// Super class' ctor makes defensive parameter copy
@@ -42,7 +39,6 @@
* Returns a copy of the encoded key bytes.
*
* @return a copy of the encoded key bytes.
- * @since Android 1.0
*/
public byte[] getEncoded() {
// Super class' getEncoded() always returns a new array
@@ -54,7 +50,6 @@
* specification.
*
* @return the string "PKCS#8".
- * @since Android 1.0
*/
public final String getFormat() {
return "PKCS#8"; //$NON-NLS-1$
diff --git a/libcore/security/src/main/java/java/security/spec/PSSParameterSpec.java b/libcore/security/src/main/java/java/security/spec/PSSParameterSpec.java
index c6a5bc5..06c1d05 100644
--- a/libcore/security/src/main/java/java/security/spec/PSSParameterSpec.java
+++ b/libcore/security/src/main/java/java/security/spec/PSSParameterSpec.java
@@ -25,9 +25,6 @@
* Defined in the <a
* href="http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-1.html">PKCS #1 v2.1</a>
* standard.
- * </p>
- *
- * @since Android 1.0
*/
public class PSSParameterSpec implements AlgorithmParameterSpec {
@@ -40,8 +37,6 @@
* <li>salt length: {@code 20}</li>
* <li>trailer field: {@code -1}</li>
* </ul>
- *
- * @since Android 1.0
*/
public static final PSSParameterSpec DEFAULT = new PSSParameterSpec(20);
@@ -64,7 +59,6 @@
* the salt length (in bits).
* @throws IllegalArgumentException
* if {@code saltLen} is negative.
- * @since Android 1.0
*/
public PSSParameterSpec(int saltLen) {
if (saltLen < 0) {
@@ -94,7 +88,6 @@
* the trailer field value.
* @throws IllegalArgumentException
* if {@code saltLen} or {@code trailerField} is negative.
- * @since Android 1.0
*/
public PSSParameterSpec(String mdName, String mgfName,
AlgorithmParameterSpec mgfSpec, int saltLen, int trailerField) {
@@ -122,7 +115,6 @@
* Returns the length of the salt (in bits).
*
* @return the length of the salt (in bits).
- * @since Android 1.0
*/
public int getSaltLength() {
return saltLen;
@@ -132,7 +124,6 @@
* Returns the name of the message digest algorithm.
*
* @return the name of the message digest algorithm.
- * @since Android 1.0
*/
public String getDigestAlgorithm() {
return mdName;
@@ -142,7 +133,6 @@
* Returns the name of the mask generation function algorithm.
*
* @return the name of the mask generation function algorithm.
- * @since Android 1.0
*/
public String getMGFAlgorithm() {
return mgfName;
@@ -153,7 +143,6 @@
*
* @return the parameter for the mask generation function algorithm, or
* {@code null} if none specified.
- * @since Android 1.0
*/
public AlgorithmParameterSpec getMGFParameters() {
return mgfSpec;
@@ -163,7 +152,6 @@
* Returns the trailer field value.
*
* @return the trailer field value.
- * @since Android 1.0
*/
public int getTrailerField() {
return trailerField;
diff --git a/libcore/security/src/main/java/java/security/spec/RSAKeyGenParameterSpec.java b/libcore/security/src/main/java/java/security/spec/RSAKeyGenParameterSpec.java
index 06f3498..2377c75 100644
--- a/libcore/security/src/main/java/java/security/spec/RSAKeyGenParameterSpec.java
+++ b/libcore/security/src/main/java/java/security/spec/RSAKeyGenParameterSpec.java
@@ -21,22 +21,16 @@
/**
* The parameter specification for generating an RSA key pair.
- *
- * @since Android 1.0
*/
public class RSAKeyGenParameterSpec implements AlgorithmParameterSpec {
/**
* The value of the public exponent {@code F0} = 3.
- *
- * @since Android 1.0
*/
public static final BigInteger F0 = BigInteger.valueOf(3L);
/**
* The value of the public exponent {@code F4} = 65537.
- *
- * @since Android 1.0
*/
public static final BigInteger F4 = BigInteger.valueOf(65537L);
@@ -53,7 +47,6 @@
* the size of the modulus (number of bits).
* @param publicExponent
* the value of the public exponent.
- * @since Android 1.0
*/
public RSAKeyGenParameterSpec(int keysize, BigInteger publicExponent) {
this.keysize = keysize;
@@ -64,7 +57,6 @@
* Returns the size of the modulus (number of bits).
*
* @return the size of the modulus (number of bits).
- * @since Android 1.0
*/
public int getKeysize() {
return keysize;
@@ -74,7 +66,6 @@
* Returns the value of the public exponent.
*
* @return the value of the public exponent.
- * @since Android 1.0
*/
public BigInteger getPublicExponent() {
return publicExponent;
diff --git a/libcore/security/src/main/java/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java b/libcore/security/src/main/java/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java
index 93e3193..28469d7 100644
--- a/libcore/security/src/main/java/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java
+++ b/libcore/security/src/main/java/java/security/spec/RSAMultiPrimePrivateCrtKeySpec.java
@@ -28,9 +28,6 @@
* Defined in the <a
* href="http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-1.html">PKCS #1 v2.1</a>
* standard.
- * </p>
- *
- * @since Android 1.0
*/
public class RSAMultiPrimePrivateCrtKeySpec extends RSAPrivateKeySpec {
// Public Exponent
@@ -74,7 +71,6 @@
* there are only the two primes ({@code p, q}).
* @throws IllegalArgumentException
* if {@code otherPrimeInfo} is not null but empty.
- * @since Android 1.0
*/
public RSAMultiPrimePrivateCrtKeySpec(
BigInteger modulus,
@@ -139,7 +135,6 @@
* Returns the CRT coefficient, {@code q^-1 mod p}.
*
* @return the CRT coefficient, {@code q^-1 mod p}.
- * @since Android 1.0
*/
public BigInteger getCrtCoefficient() {
return crtCoefficient;
@@ -150,7 +145,6 @@
*
* @return the information for the additional primes, or {@code null} if
* there are only the two primes ({@code p, q}).
- * @since Android 1.0
*/
public RSAOtherPrimeInfo[] getOtherPrimeInfo() {
// Clone array (if not null) to prevent subsequent modification
@@ -168,7 +162,6 @@
* Returns the exponent of the prime {@code p}.
*
* @return the exponent of the prime {@code p}.
- * @since Android 1.0
*/
public BigInteger getPrimeExponentP() {
return primeExponentP;
@@ -178,7 +171,6 @@
* Returns the exponent of the prime {@code q}.
*
* @return the exponent of the prime {@code q}.
- * @since Android 1.0
*/
public BigInteger getPrimeExponentQ() {
return primeExponentQ;
@@ -188,7 +180,6 @@
* Returns the prime factor {@code p}.
*
* @return the prime factor {@code p}.
- * @since Android 1.0
*/
public BigInteger getPrimeP() {
return primeP;
@@ -198,7 +189,6 @@
* Returns the prime factor {@code q}.
*
* @return the prime factor {@code q}.
- * @since Android 1.0
*/
public BigInteger getPrimeQ() {
return primeQ;
@@ -208,7 +198,6 @@
* Returns the public exponent {@code e}.
*
* @return the public exponent {@code e}.
- * @since Android 1.0
*/
public BigInteger getPublicExponent() {
return publicExponent;
diff --git a/libcore/security/src/main/java/java/security/spec/RSAOtherPrimeInfo.java b/libcore/security/src/main/java/java/security/spec/RSAOtherPrimeInfo.java
index 9b4828e..177ddf5 100644
--- a/libcore/security/src/main/java/java/security/spec/RSAOtherPrimeInfo.java
+++ b/libcore/security/src/main/java/java/security/spec/RSAOtherPrimeInfo.java
@@ -28,9 +28,6 @@
* Defined in the <a
* href="http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-1.html">PKCS #1 v2.1</a>
* standard.
- * </p>
- *
- * @since Android 1.0
*/
public class RSAOtherPrimeInfo {
// Prime
@@ -50,7 +47,6 @@
* the prime exponent.
* @param crtCoefficient
* the CRT coefficient.
- * @since Android 1.0
*/
public RSAOtherPrimeInfo(BigInteger prime,
BigInteger primeExponent, BigInteger crtCoefficient) {
@@ -72,7 +68,6 @@
* Returns the CRT coefficient.
*
* @return the CRT coefficient.
- * @since Android 1.0
*/
public final BigInteger getCrtCoefficient() {
return crtCoefficient;
@@ -82,7 +77,6 @@
* Returns the prime factor.
*
* @return the prime factor.
- * @since Android 1.0
*/
public final BigInteger getPrime() {
return prime;
@@ -92,7 +86,6 @@
* Returns the exponent.
*
* @return the exponent.
- * @since Android 1.0
*/
public final BigInteger getExponent() {
return primeExponent;
diff --git a/libcore/security/src/main/java/java/security/spec/RSAPrivateCrtKeySpec.java b/libcore/security/src/main/java/java/security/spec/RSAPrivateCrtKeySpec.java
index 1157099..e786e9e 100644
--- a/libcore/security/src/main/java/java/security/spec/RSAPrivateCrtKeySpec.java
+++ b/libcore/security/src/main/java/java/security/spec/RSAPrivateCrtKeySpec.java
@@ -26,9 +26,6 @@
* Defined in the <a
* href="http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-1.html">PKCS #1 v2.1</a>
* standard.
- * </p>
- *
- * @since Android 1.0
*/
public class RSAPrivateCrtKeySpec extends RSAPrivateKeySpec {
// Public Exponent
@@ -65,7 +62,6 @@
* the exponent of the prime {@code q}.
* @param crtCoefficient
* the CRT coefficient {@code q^-1 mod p}.
- * @since Android 1.0
*/
public RSAPrivateCrtKeySpec(BigInteger modulus,
BigInteger publicExponent,
@@ -90,7 +86,6 @@
* Returns the CRT coefficient, {@code q^-1 mod p}.
*
* @return the CRT coefficient, {@code q^-1 mod p}.
- * @since Android 1.0
*/
public BigInteger getCrtCoefficient() {
return crtCoefficient;
@@ -100,7 +95,6 @@
* Returns the exponent of the prime {@code p}.
*
* @return the exponent of the prime {@code p}.
- * @since Android 1.0
*/
public BigInteger getPrimeExponentP() {
return primeExponentP;
@@ -110,7 +104,6 @@
* Returns the exponent of the prime {@code q}.
*
* @return the exponent of the prime {@code q}.
- * @since Android 1.0
*/
public BigInteger getPrimeExponentQ() {
return primeExponentQ;
@@ -120,7 +113,6 @@
* Returns the prime factor {@code p}.
*
* @return the prime factor {@code p}.
- * @since Android 1.0
*/
public BigInteger getPrimeP() {
return primeP;
@@ -130,7 +122,6 @@
* Returns the prime factor {@code q}.
*
* @return the prime factor {@code q}.
- * @since Android 1.0
*/
public BigInteger getPrimeQ() {
return primeQ;
@@ -140,7 +131,6 @@
* Returns the public exponent {@code e}.
*
* @return the public exponent {@code e}.
- * @since Android 1.0
*/
public BigInteger getPublicExponent() {
return publicExponent;
diff --git a/libcore/security/src/main/java/java/security/spec/RSAPrivateKeySpec.java b/libcore/security/src/main/java/java/security/spec/RSAPrivateKeySpec.java
index bd7d4e8..c94420e 100644
--- a/libcore/security/src/main/java/java/security/spec/RSAPrivateKeySpec.java
+++ b/libcore/security/src/main/java/java/security/spec/RSAPrivateKeySpec.java
@@ -25,9 +25,6 @@
* Defined in the <a
* href="http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-1.html">PKCS #1 v2.1</a>
* standard
- * </p>
- *
- * @since Android 1.0
*/
public class RSAPrivateKeySpec implements KeySpec {
// Modulus
@@ -43,7 +40,6 @@
* the modulus {@code n}.
* @param privateExponent
* the private exponent {@code e}
- * @since Android 1.0
*/
public RSAPrivateKeySpec(BigInteger modulus, BigInteger privateExponent) {
this.modulus = modulus;
@@ -54,7 +50,6 @@
* Returns the modulus {@code n}.
*
* @return the modulus {@code n}.
- * @since Android 1.0
*/
public BigInteger getModulus() {
return modulus;
@@ -64,7 +59,6 @@
* Returns the private exponent {@code e}.
*
* @return the private exponent {@code e}.
- * @since Android 1.0
*/
public BigInteger getPrivateExponent() {
return privateExponent;
diff --git a/libcore/security/src/main/java/java/security/spec/RSAPublicKeySpec.java b/libcore/security/src/main/java/java/security/spec/RSAPublicKeySpec.java
index bd4c5b5..fe6de07 100644
--- a/libcore/security/src/main/java/java/security/spec/RSAPublicKeySpec.java
+++ b/libcore/security/src/main/java/java/security/spec/RSAPublicKeySpec.java
@@ -25,8 +25,6 @@
* Defined in the <a
* href="http://www.rsa.com/rsalabs/pubs/PKCS/html/pkcs-1.html">PKCS #1 v2.1</a>
* standard.
- * </p>
- * @since Android 1.0
*/
public class RSAPublicKeySpec implements KeySpec {
// Modulus
@@ -42,7 +40,6 @@
* the modulus {@code n}.
* @param publicExponent
* the public exponent {@code d}.
- * @since Android 1.0
*/
public RSAPublicKeySpec(BigInteger modulus, BigInteger publicExponent) {
this.modulus = modulus;
@@ -53,7 +50,6 @@
* Returns the modulus {@code n}.
*
* @return the modulus {@code n}.
- * @since Android 1.0
*/
public BigInteger getModulus() {
return modulus;
@@ -63,7 +59,6 @@
* Returns the public exponent {@code d}.
*
* @return the public exponent {@code d}.
- * @since Android 1.0
*/
public BigInteger getPublicExponent() {
return publicExponent;
diff --git a/libcore/security/src/main/java/java/security/spec/X509EncodedKeySpec.java b/libcore/security/src/main/java/java/security/spec/X509EncodedKeySpec.java
index 6cc6104..61f3475 100644
--- a/libcore/security/src/main/java/java/security/spec/X509EncodedKeySpec.java
+++ b/libcore/security/src/main/java/java/security/spec/X509EncodedKeySpec.java
@@ -19,8 +19,6 @@
/**
* The key specification of an X.509 encoded key in ASN.1 format.
- *
- * @since Android 1.0
*/
public class X509EncodedKeySpec extends EncodedKeySpec {
@@ -30,7 +28,6 @@
*
* @param encodedKey
* the encoded key bytes.
- * @since Android 1.0
*/
public X509EncodedKeySpec(byte[] encodedKey) {
// Super class' ctor makes defensive parameter copy
@@ -41,7 +38,6 @@
* Returns the encoded key bytes.
*
* @return the encoded key bytes.
- * @since Android 1.0
*/
public byte[] getEncoded() {
// Super class' getEncoded() always returns a new array
@@ -53,7 +49,6 @@
* specification.
*
* @return the string "X.509".
- * @since Android 1.0
*/
public final String getFormat() {
return "X.509"; //$NON-NLS-1$
diff --git a/libcore/security/src/main/java/javax/security/cert/Certificate.java b/libcore/security/src/main/java/javax/security/cert/Certificate.java
index fb00789..ef513a3 100644
--- a/libcore/security/src/main/java/javax/security/cert/Certificate.java
+++ b/libcore/security/src/main/java/javax/security/cert/Certificate.java
@@ -29,34 +29,30 @@
/**
* Abstract class to represent identity certificates. It represents a way to
* verify the binding of a Principal and its public key. Examples are X.509,
- * PGP, and SDSI.
+ * PGP, and SDSI.
* <p>
* Note: This package is provided only for compatibility reasons.
* It contains a simplified version of the java.security.cert package that was
* previously used by JSSE (Java SSL package). All applications that do not have
* to be compatible with older versions of JSSE (that is before Java SDK 1.5)
* should only use java.security.cert.
- * </p>
- * @since Android 1.0
*/
public abstract class Certificate {
/**
* Creates a new {@code Certificate}.
- * @since Android 1.0
*/
public Certificate() {}
/**
* Compares the argument to this Certificate. If both have the same bytes
* they are assumed to be equal.
- *
+ *
* @param obj
* the {@code Certificate} to compare with this object
* @return <code>true</code> if {@code obj} is the same as this
* {@code Certificate}, <code>false</code> otherwise
* @see #hashCode
- * @since Android 1.0
*/
public boolean equals(Object obj) {
if (obj == this) {
@@ -77,10 +73,9 @@
* Returns an integer hash code for the receiver. Any two objects which
* return <code>true</code> when passed to <code>equals</code> must answer
* the same value for this method.
- *
+ *
* @return the receiver's hash
* @see #equals
- * @since Android 1.0
*/
public int hashCode() {
int res = 0;
@@ -96,18 +91,17 @@
/**
* Returns the encoded representation for this certificate.
- *
+ *
* @return the encoded representation for this certificate.
* @throws CertificateEncodingException
* if encoding fails.
- * @since Android 1.0
*/
public abstract byte[] getEncoded()
throws CertificateEncodingException;
/**
* Verifies that this certificate was signed with the given public key.
- *
+ *
* @param key
* public key for which verification should be performed.
* @throws CertificateException
@@ -120,7 +114,6 @@
* if there is no default provider
* @throws SignatureException
* if signature errors are detected
- * @since Android 1.0
*/
public abstract void verify(PublicKey key)
throws CertificateException, NoSuchAlgorithmException,
@@ -130,7 +123,7 @@
/**
* Verifies that this certificate was signed with the given public key. Uses
* the signature algorithm given by the provider.
- *
+ *
* @param key
* public key for which verification should be performed.
* @param sigProvider
@@ -145,7 +138,6 @@
* if the specified provider does not exists.
* @exception SignatureException
* if signature errors are detected
- * @since Android 1.0
*/
public abstract void verify(PublicKey key, String sigProvider)
throws CertificateException, NoSuchAlgorithmException,
@@ -155,17 +147,15 @@
/**
* Returns a string containing a concise, human-readable description of the
* receiver.
- *
+ *
* @return a printable representation for the receiver.
- * @since Android 1.0
*/
public abstract String toString();
/**
* Returns the public key corresponding to this certificate.
- *
+ *
* @return the public key corresponding to this certificate.
- * @since Android 1.0
*/
public abstract PublicKey getPublicKey();
}
diff --git a/libcore/security/src/main/java/javax/security/cert/CertificateEncodingException.java b/libcore/security/src/main/java/javax/security/cert/CertificateEncodingException.java
index 4091695..780e43f 100644
--- a/libcore/security/src/main/java/javax/security/cert/CertificateEncodingException.java
+++ b/libcore/security/src/main/java/javax/security/cert/CertificateEncodingException.java
@@ -27,20 +27,20 @@
* by JSSE (Java SSL package). All applications that do not have to be
* compatible with older versions of JSSE (that is before Java SDK 1.5) should
* only use java.security.cert.
- * </p>
- * @since Android 1.0
*/
public class CertificateEncodingException extends CertificateException {
+ /**
+ * @serial
+ */
private static final long serialVersionUID = -8187642723048403470L;
/**
* Creates a new {@code CertificateEncodingException} with the specified
* message.
- *
+ *
* @param msg
* the detail message for the exception.
- * @since Android 1.0
*/
public CertificateEncodingException(String msg) {
super(msg);
@@ -48,9 +48,7 @@
/**
* Creates a new {@code CertificateEncodingException}.
- *
- * @since Android 1.0
*/
public CertificateEncodingException() {
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/javax/security/cert/CertificateException.java b/libcore/security/src/main/java/javax/security/cert/CertificateException.java
index f186e51..fd2a614 100644
--- a/libcore/security/src/main/java/javax/security/cert/CertificateException.java
+++ b/libcore/security/src/main/java/javax/security/cert/CertificateException.java
@@ -26,19 +26,19 @@
* by JSSE (Java SSL package). All applications that do not have to be
* compatible with older versions of JSSE (that is before Java SDK 1.5) should
* only use java.security.cert.
- * </p>
- * @since Android 1.0
*/
public class CertificateException extends Exception {
+ /**
+ * @serial
+ */
private static final long serialVersionUID = -5757213374030785290L;
/**
* Creates a new {@code CertificateException} with the specified message.
- *
+ *
* @param msg
* the detail message for the exception.
- * @since Android 1.0
*/
public CertificateException(String msg) {
super(msg);
@@ -46,9 +46,7 @@
/**
* Creates a new {@code CertificateException}.
- *
- * @since Android 1.0
*/
public CertificateException() {
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/javax/security/cert/CertificateExpiredException.java b/libcore/security/src/main/java/javax/security/cert/CertificateExpiredException.java
index 62870a6..94e6558 100644
--- a/libcore/security/src/main/java/javax/security/cert/CertificateExpiredException.java
+++ b/libcore/security/src/main/java/javax/security/cert/CertificateExpiredException.java
@@ -25,20 +25,20 @@
* by JSSE (Java SSL package). All applications that do not have to be
* compatible with older versions of JSSE (that is before Java SDK 1.5) should
* only use java.security.cert.
- * </p>
- * @since Android 1.0
*/
public class CertificateExpiredException extends CertificateException {
+ /**
+ * @serial
+ */
private static final long serialVersionUID = 5091601212177261883L;
/**
* Creates a new {@code CertificateExpiredException} with the specified
* message.
- *
+ *
* @param msg
* the detail message for this exception
- * @since Android 1.0
*/
public CertificateExpiredException(String msg) {
super(msg);
@@ -46,9 +46,7 @@
/**
* Creates a new {@code CertificateExpiredException}.
- *
- * @since Android 1.0
*/
public CertificateExpiredException() {
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/javax/security/cert/CertificateNotYetValidException.java b/libcore/security/src/main/java/javax/security/cert/CertificateNotYetValidException.java
index 6f32945..8fe0a33 100644
--- a/libcore/security/src/main/java/javax/security/cert/CertificateNotYetValidException.java
+++ b/libcore/security/src/main/java/javax/security/cert/CertificateNotYetValidException.java
@@ -25,20 +25,20 @@
* by JSSE (Java SSL package). All applications that do not have to be
* compatible with older versions of JSSE (that is before Java SDK 1.5) should
* only use java.security.cert.
- * </p>
- * @since Android 1.0
*/
public class CertificateNotYetValidException extends CertificateException {
+ /**
+ * @serial
+ */
private static final long serialVersionUID = -8976172474266822818L;
/**
* Creates a new {@code CertificateNotYetValidException} with the specified
* message.
- *
+ *
* @param msg
* the detail message for the exception.
- * @since Android 1.0
*/
public CertificateNotYetValidException(String msg) {
super(msg);
@@ -46,9 +46,7 @@
/**
* Creates a new {@code CertificateNotYetValidException}.
- *
- * @since Android 1.0
*/
public CertificateNotYetValidException() {
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/javax/security/cert/CertificateParsingException.java b/libcore/security/src/main/java/javax/security/cert/CertificateParsingException.java
index 9b208e6..48986c0 100644
--- a/libcore/security/src/main/java/javax/security/cert/CertificateParsingException.java
+++ b/libcore/security/src/main/java/javax/security/cert/CertificateParsingException.java
@@ -25,20 +25,20 @@
* by JSSE (Java SSL package). All applications that do not have to be
* compatible with older versions of JSSE (that is before Java SDK 1.5) should
* only use java.security.cert.
- * </p>
- * @since Android 1.0
*/
public class CertificateParsingException extends CertificateException {
+ /**
+ * @serial
+ */
private static final long serialVersionUID = -8449352422951136229L;
/**
* Creates a new {@code CertificateParsingException} with the specified
* message.
- *
+ *
* @param msg
* the detail message for the exception.
- * @since Android 1.0
*/
public CertificateParsingException(String msg) {
super(msg);
@@ -46,9 +46,7 @@
/**
* Creates a new {@code CertificateParsingException}.
- *
- * @since Android 1.0
*/
public CertificateParsingException() {
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/javax/security/cert/X509Certificate.java b/libcore/security/src/main/java/javax/security/cert/X509Certificate.java
index 77bffae..8877386 100644
--- a/libcore/security/src/main/java/javax/security/cert/X509Certificate.java
+++ b/libcore/security/src/main/java/javax/security/cert/X509Certificate.java
@@ -44,15 +44,12 @@
* <p>
* This represents a standard way for accessing the attributes of X.509 v1
* certificates.
- * </p>
* <p>
* Note: This package is provided only for compatibility reasons.
* It contains a simplified version of the java.security.cert package that was
* previously used by JSSE (Java SSL package). All applications that do not have
* to be compatible with older versions of JSSE (that is before Java SDK 1.5)
* should only use java.security.cert.
- * </p>
- * @since Android 1.0
*/
public abstract class X509Certificate extends Certificate {
@@ -76,8 +73,6 @@
/**
* Creates a new {@code X509Certificate}.
- *
- * @since Android 1.0
*/
public X509Certificate() {
super();
@@ -86,13 +81,12 @@
/**
* Creates a new {@code X509Certificate} and initializes it from the
* specified input stream.
- *
+ *
* @param inStream
* input stream containing data to initialize the certificate.
* @return the certificate initialized from the specified input stream
* @throws CertificateException
* if the certificate cannot be created or initialized.
- * @since Android 1.0
*/
public static final X509Certificate getInstance(InputStream inStream)
throws CertificateException {
@@ -220,13 +214,12 @@
/**
* Creates a new {@code X509Certificate} and initializes it from the
* specified byte array.
- *
+ *
* @param certData
* byte array containing data to initialize the certificate.
* @return the certificate initialized from the specified byte array
* @throws CertificateException
* if the certificate cannot be created or initialized.
- * @since Android 1.0
*/
public static final X509Certificate getInstance(byte[] certData)
throws CertificateException {
@@ -241,26 +234,23 @@
* Checks whether the certificate is currently valid.
* <p>
* The validity defined in ASN.1:
- *
+ *
* <pre>
* validity Validity
- *
- * Validity ::= SEQUENCE {
- * notBefore CertificateValidityDate,
+ *
+ * Validity ::= SEQUENCE {
+ * notBefore CertificateValidityDate,
* notAfter CertificateValidityDate }
- *
- * CertificateValidityDate ::= CHOICE {
- * utcTime UTCTime,
+ *
+ * CertificateValidityDate ::= CHOICE {
+ * utcTime UTCTime,
* generalTime GeneralizedTime }
* </pre>
- *
- * </p>
- *
+ *
* @throws CertificateExpiredException
* if the certificate has expired.
* @throws CertificateNotYetValidException
* if the certificate is not yet valid.
- * @since Android 1.0
*/
public abstract void checkValidity()
throws CertificateExpiredException, CertificateNotYetValidException;
@@ -268,7 +258,7 @@
/**
* Checks whether the certificate is valid at the specified date.
- *
+ *
* @param date
* the date to check the validity against.
* @throws CertificateExpiredException
@@ -276,7 +266,6 @@
* @throws CertificateNotYetValidException
* if the certificate is not yet valid.
* @see #checkValidity()
- * @since Android 1.0
*/
public abstract void checkValidity(Date date)
throws CertificateExpiredException, CertificateNotYetValidException;
@@ -285,15 +274,12 @@
* Returns the certificates {@code version} (version number).
* <p>
* The version defined is ASN.1:
- *
+ *
* <pre>
* Version ::= INTEGER { v1(0), v2(1), v3(2) }
* </pre>
- *
- * </p>
- *
+ *
* @return the version number.
- * @since Android 1.0
*/
public abstract int getVersion();
@@ -301,15 +287,12 @@
* Returns the {@code serialNumber} of the certificate.
* <p>
* The ASN.1 definition of {@code serialNumber}:
- *
+ *
* <pre>
* CertificateSerialNumber ::= INTEGER
* </pre>
- *
- * </p>
- *
+ *
* @return the serial number.
- * @since Android 1.0
*/
public abstract BigInteger getSerialNumber();
@@ -318,31 +301,28 @@
* implementation specific {@code Principal} object.
* <p>
* The ASN.1 definition of {@code issuer}:
- *
+ *
* <pre>
* issuer Name
- *
+ *
* Name ::= CHOICE {
* RDNSequence }
- *
+ *
* RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
- *
+ *
* RelativeDistinguishedName ::= SET OF AttributeTypeAndValue
- *
+ *
* AttributeTypeAndValue ::= SEQUENCE {
* type AttributeType,
* value AttributeValue }
- *
+ *
* AttributeType ::= OBJECT IDENTIFIER
- *
+ *
* AttributeValue ::= ANY DEFINED BY AttributeType
* </pre>
- *
- * </p>
- *
+ *
* @return the {@code issuer} as an implementation specific {@code
* Principal}.
- * @since Android 1.0
*/
public abstract Principal getIssuerDN();
@@ -351,73 +331,65 @@
* implementation specific {@code Principal} object.
* <p>
* The ASN.1 definition of {@code subject}:
- *
+ *
* <pre>
* subject Name
- *
+ *
* Name ::= CHOICE {
* RDNSequence }
- *
+ *
* RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
- *
+ *
* RelativeDistinguishedName ::= SET OF AttributeTypeAndValue
- *
+ *
* AttributeTypeAndValue ::= SEQUENCE {
* type AttributeType,
* value AttributeValue }
- *
+ *
* AttributeType ::= OBJECT IDENTIFIER
- *
+ *
* AttributeValue ::= ANY DEFINED BY AttributeType
* </pre>
- *
- * </p>
- *
+ *
* @return the {@code subject} (subject distinguished name).
- * @since Android 1.0
*/
public abstract Principal getSubjectDN();
/**
* Returns the {@code notBefore} date from the validity period of the
* certificate.
- *
+ *
* @return the start of the validity period.
- * @since Android 1.0
*/
public abstract Date getNotBefore();
/**
* Returns the {@code notAfter} date of the validity period of the
* certificate.
- *
+ *
* @return the end of the validity period.
- * @since Android 1.0
*/
public abstract Date getNotAfter();
/**
* Returns the name of the algorithm for the certificate signature.
- *
+ *
* @return the signature algorithm name.
- * @since Android 1.0
*/
public abstract String getSigAlgName();
/**
* Returns the OID of the signature algorithm from the certificate.
- *
+ *
* @return the OID of the signature algorithm.
- * @since Android 1.0
*/
public abstract String getSigAlgOID();
/**
* Returns the parameters of the signature algorithm in DER-encoded format.
- *
+ *
* @return the parameters of the signature algorithm, or null if none are
* used.
- * @since Android 1.0
*/
public abstract byte[] getSigAlgParams();
}
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/DefaultPolicyScanner.java b/libcore/security/src/main/java/org/apache/harmony/security/DefaultPolicyScanner.java
index ba3229b..afab96e 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/DefaultPolicyScanner.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/DefaultPolicyScanner.java
@@ -127,9 +127,9 @@
break parsing;
case StreamTokenizer.TT_WORD:
- if ("keystore".equalsIgnoreCase(st.sval)) { //$NON-NLS-1$
+ if (Util.equalsIgnoreCase("keystore", st.sval)) { //$NON-NLS-1$
keystoreEntries.add(readKeystoreEntry(st));
- } else if ("grant".equalsIgnoreCase(st.sval)) { //$NON-NLS-1$
+ } else if (Util.equalsIgnoreCase("grant", st.sval)) { //$NON-NLS-1$
grantEntries.add(readGrantEntry(st));
} else {
handleUnexpectedToken(st, Messages.getString("security.89")); //$NON-NLS-1$
@@ -208,19 +208,19 @@
switch (st.nextToken()) {
case StreamTokenizer.TT_WORD:
- if ("signedby".equalsIgnoreCase(st.sval)) { //$NON-NLS-1$
+ if (Util.equalsIgnoreCase("signedby", st.sval)) { //$NON-NLS-1$
if (st.nextToken() == '"') {
ge.signers = st.sval;
} else {
handleUnexpectedToken(st, Messages.getString("security.8B")); //$NON-NLS-1$
}
- } else if ("codebase".equalsIgnoreCase(st.sval)) { //$NON-NLS-1$
+ } else if (Util.equalsIgnoreCase("codebase", st.sval)) { //$NON-NLS-1$
if (st.nextToken() == '"') {
ge.codebase = st.sval;
} else {
handleUnexpectedToken(st, Messages.getString("security.8C")); //$NON-NLS-1$
}
- } else if ("principal".equalsIgnoreCase(st.sval)) { //$NON-NLS-1$
+ } else if (Util.equalsIgnoreCase("principal", st.sval)) { //$NON-NLS-1$
ge.addPrincipal(readPrincipalEntry(st));
} else {
handleUnexpectedToken(st);
@@ -308,7 +308,7 @@
switch (st.nextToken()) {
case StreamTokenizer.TT_WORD:
- if ("permission".equalsIgnoreCase(st.sval)) { //$NON-NLS-1$
+ if (Util.equalsIgnoreCase("permission", st.sval)) { //$NON-NLS-1$
PermissionEntry pe = new PermissionEntry();
if (st.nextToken() == StreamTokenizer.TT_WORD) {
pe.klass = st.sval;
@@ -326,7 +326,7 @@
}
}
if (st.ttype == StreamTokenizer.TT_WORD
- && "signedby".equalsIgnoreCase(st.sval)) { //$NON-NLS-1$
+ && Util.equalsIgnoreCase("signedby", st.sval)) { //$NON-NLS-1$
if (st.nextToken() == '"') {
pe.signers = st.sval;
} else {
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/PolicyEntry.java b/libcore/security/src/main/java/org/apache/harmony/security/PolicyEntry.java
index 4c7aa5b..0037ad6 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/PolicyEntry.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/PolicyEntry.java
@@ -22,6 +22,8 @@
package org.apache.harmony.security;
+import java.net.URL;
+import java.security.CodeSigner;
import java.security.CodeSource;
import java.security.Permission;
import java.security.Principal;
@@ -30,7 +32,6 @@
import org.apache.harmony.security.fortress.PolicyUtils;
-
/**
* This class represents an elementary block of a security policy. It associates
* a CodeSource of an executable code, Principals allowed to execute the code,
@@ -55,7 +56,7 @@
*/
public PolicyEntry(CodeSource cs, Collection<? extends Principal> prs,
Collection<? extends Permission> permissions) {
- this.cs = cs;
+ this.cs = (cs != null) ? normalizeCodeSource(cs) : null;
this.principals = (prs == null || prs.isEmpty()) ? null
: (Principal[]) prs.toArray(new Principal[prs.size()]);
this.permissions = (permissions == null || permissions.isEmpty()) ? null
@@ -68,7 +69,31 @@
* imply() method.
*/
public boolean impliesCodeSource(CodeSource codeSource) {
- return (cs == null) ? true : cs.implies(codeSource);
+ if (cs == null) {
+ return true;
+ }
+
+ if (codeSource == null) {
+ return false;
+ }
+ return cs.implies(normalizeCodeSource(codeSource));
+ }
+
+ private CodeSource normalizeCodeSource(CodeSource codeSource) {
+ URL codeSourceURL = PolicyUtils.normalizeURL(codeSource.getLocation());
+ CodeSource result = codeSource;
+
+ if (codeSourceURL != codeSource.getLocation()) {
+ // URL was normalized - recreate codeSource with new URL
+ CodeSigner[] signers = codeSource.getCodeSigners();
+ if (signers == null) {
+ result = new CodeSource(codeSourceURL, codeSource
+ .getCertificates());
+ } else {
+ result = new CodeSource(codeSourceURL, signers);
+ }
+ }
+ return result;
}
/**
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/Util.java b/libcore/security/src/main/java/org/apache/harmony/security/Util.java
new file mode 100644
index 0000000..e6e764f
--- /dev/null
+++ b/libcore/security/src/main/java/org/apache/harmony/security/Util.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.harmony.security;
+
+public class Util {
+
+ public static String toUpperCase(String s) {
+ return org.apache.harmony.luni.util.Util.toASCIIUpperCase(s);
+ }
+
+ public static boolean equalsIgnoreCase(String s1, String s2) {
+ s1 = org.apache.harmony.luni.util.Util.toASCIIUpperCase(s1);
+ s2 = org.apache.harmony.luni.util.Util.toASCIIUpperCase(s2);
+ return s1.equals(s2);
+ }
+}
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1Choice.java b/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1Choice.java
index 1f5534d..e8db789 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1Choice.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1Choice.java
@@ -25,6 +25,7 @@
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Iterator;
+import java.util.Map;
import java.util.TreeMap;
import org.apache.harmony.security.internal.nls.Messages;
@@ -269,12 +270,14 @@
// fill identifiers array
int size = map.size();
identifiers = new int[2][size];
- Iterator it = map.keySet().iterator();
+ Iterator it = map.entrySet().iterator();
+
for (int i = 0; i < size; i++) {
- BigInteger identifier = (BigInteger) it.next();
+ Map.Entry entry = (Map.Entry) it.next();
+ BigInteger identifier = (BigInteger) entry.getKey();
identifiers[0][i] = identifier.intValue();
- identifiers[1][i] = ((BigInteger) map.get(identifier)).intValue();
+ identifiers[1][i] = ((BigInteger) entry.getValue()).intValue();
}
this.type = type;
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1GeneralizedTime.java b/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1GeneralizedTime.java
index 4ec103b..4908afb 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1GeneralizedTime.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1GeneralizedTime.java
@@ -23,6 +23,7 @@
package org.apache.harmony.security.asn1;
import java.io.IOException;
+import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
@@ -30,10 +31,7 @@
/**
* This class represents ASN.1 GeneralizedTime type.
*
- * According to X.680 specification this type is defined as follows:
- * GeneralizedTime ::= [UNIVERSAL 24] IMPLICIT VisibleString
- *
- * @see <a href="http://asn1.elibel.tm.fr/en/standards/index.htm">ASN.1</a>
+ * @see http://asn1.elibel.tm.fr/en/standards/index.htm
*/
public class ASN1GeneralizedTime extends ASN1Time {
@@ -114,7 +112,13 @@
if (temp.charAt(currLength) == '.') {
temp = temp.substring(0, currLength);
}
- out.content = (temp + "Z").getBytes(); //$NON-NLS-1$
+
+ try {
+ out.content = (temp + "Z").getBytes("UTF-8"); //$NON-NLS-1$ //$NON-NLS-2$
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e.getMessage());
+ }
+
out.length = ((byte[]) out.content).length;
}
}
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1Oid.java b/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1Oid.java
index 6292870..960dc0f 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1Oid.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1Oid.java
@@ -154,7 +154,7 @@
public Object getDecodedObject(BerInputStream in) throws IOException {
- StringBuffer buf = new StringBuffer();
+ StringBuilder buf = new StringBuilder();
int element;
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1StringType.java b/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1StringType.java
index 55f48fa..0bc4b8a 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1StringType.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1StringType.java
@@ -118,7 +118,9 @@
* @return java.land.String object
*/
public Object getDecodedObject(BerInputStream in) throws IOException {
- return new String(in.buffer, in.contentOffset, in.length);
+ /* To ensure we get the correct encoding on non-ASCII platforms, specify
+ that we wish to convert from ASCII to the default platform encoding */
+ return new String(in.buffer, in.contentOffset, in.length, "ISO-8859-1");
}
//
@@ -137,11 +139,15 @@
}
public void setEncodingContent(BerOutputStream out) {
-
- byte[] bytes = ((String) out.content).getBytes();
-
- out.content = bytes;
- out.length = bytes.length;
+ try {
+ byte[] bytes = ((String) out.content).getBytes("UTF-8"); //$NON-NLS-1$
+ out.content = bytes;
+ out.length = bytes.length;
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e.getMessage());
+ }
}
}
+
+
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1UTCTime.java b/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1UTCTime.java
index 0dd7ae4..3d2cb3e 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1UTCTime.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/asn1/ASN1UTCTime.java
@@ -23,6 +23,7 @@
package org.apache.harmony.security.asn1;
import java.io.IOException;
+import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
@@ -30,10 +31,7 @@
/**
* This class represents ASN.1 UTCTime type
*
- * According to X.680 specification this type is defined as follows:
- * UTCTime ::= [UNIVERSAL 23] IMPLICIT VisibleString
- *
- * @see <a href="http://asn1.elibel.tm.fr/en/standards/index.htm">ASN.1</a>
+ * @see http://asn1.elibel.tm.fr/en/standards/index.htm
*/
public class ASN1UTCTime extends ASN1Time {
@@ -118,7 +116,11 @@
public void setEncodingContent(BerOutputStream out) {
SimpleDateFormat sdf = new SimpleDateFormat(UTC_PATTERN);
sdf.setTimeZone(TimeZone.getTimeZone("UTC")); //$NON-NLS-1$
- out.content = sdf.format(out.content).getBytes();
+ try {
+ out.content = sdf.format(out.content).getBytes("UTF-8"); //$NON-NLS-1$
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e.getMessage());
+ }
out.length = ((byte[]) out.content).length;
}
}
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/asn1/BerInputStream.java b/libcore/security/src/main/java/org/apache/harmony/security/asn1/BerInputStream.java
index 68819b8..531d760 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/asn1/BerInputStream.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/asn1/BerInputStream.java
@@ -25,7 +25,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
-import java.util.Calendar;
import org.apache.harmony.security.internal.nls.Messages;
@@ -132,8 +131,8 @@
if (length != INDEFINIT_LENGTH) {
// input stream has definite length encoding
// check allocated length to avoid further reallocations
- if (buffer.length < length) {
- byte[] newBuffer = new byte[length];
+ if (buffer.length < (length + offset)) {
+ byte[] newBuffer = new byte[length + offset];
System.arraycopy(buffer, 0, newBuffer, 0, offset);
buffer = newBuffer;
}
@@ -916,9 +915,22 @@
if (in == null) {
offset += length;
} else {
- if (in.read(buffer, offset, length) != length) {
- throw new ASN1Exception(Messages.getString("security.13C")); //$NON-NLS-1$
+ int bytesRead = in.read(buffer, offset, length);
+
+ if (bytesRead != length) {
+ // if input stream didn't return all data at once
+ // try to read it in several blocks
+ int c = bytesRead;
+ do {
+ if (c < 1 || bytesRead > length) {
+ throw new ASN1Exception(Messages
+ .getString("security.13C")); //$NON-NLS-1$
+ }
+ c = in.read(buffer, offset + bytesRead, length - bytesRead);
+ bytesRead += c;
+ } while (bytesRead != length);
}
+
offset += length;
}
}
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/asn1/InformationObjectSet.java b/libcore/security/src/main/java/org/apache/harmony/security/asn1/InformationObjectSet.java
index 2a267e5..06ada53 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/asn1/InformationObjectSet.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/asn1/InformationObjectSet.java
@@ -95,7 +95,7 @@
return intHash & 0x7FFFFFFF; // only positive
}
- private class Entry {
+ private static class Entry {
public int[] oid;
public Object object;
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/asn1/ObjectIdentifier.java b/libcore/security/src/main/java/org/apache/harmony/security/asn1/ObjectIdentifier.java
index 0e7269a..0d3a77a 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/asn1/ObjectIdentifier.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/asn1/ObjectIdentifier.java
@@ -243,7 +243,7 @@
* @return oid string representation
*/
public static String toString(int[] oid) {
- StringBuffer sb = new StringBuffer(3 * oid.length);
+ StringBuilder sb = new StringBuilder(3 * oid.length);
for (int i = 0; i < oid.length - 1; ++i) {
sb.append(oid[i]);
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/fortress/DefaultPolicy.java b/libcore/security/src/main/java/org/apache/harmony/security/fortress/DefaultPolicy.java
index 2aa474e..df425a4 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/fortress/DefaultPolicy.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/fortress/DefaultPolicy.java
@@ -163,7 +163,7 @@
// A flag indicating brand new instance which needs to be loaded
// on the first appeal to it's data.
- private boolean initiailized;
+ private boolean initialized;
/**
* Default constructor, equivalent to
@@ -180,7 +180,7 @@
*/
public DefaultPolicy(DefaultPolicyParser dpr) {
parser = dpr;
- initiailized = false;
+ initialized = false;
refresh();
}
@@ -191,9 +191,9 @@
* to be <code>null</code> if the domain is <code>null</code>.
*/
public PermissionCollection getPermissions(ProtectionDomain pd) {
- if (!initiailized) {
+ if (!initialized) {
synchronized (this) {
- if (!initiailized) {
+ if (!initialized) {
refresh();
}
}
@@ -230,9 +230,9 @@
* The evaluation assumes that current principals are undefined.
*/
public PermissionCollection getPermissions(CodeSource cs) {
- if (!initiailized) {
+ if (!initialized) {
synchronized (this) {
- if (!initiailized) {
+ if (!initialized) {
refresh();
}
}
@@ -306,6 +306,6 @@
cache.clear();
}
- initiailized = true;
+ initialized = true;
}
}
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/fortress/DefaultPolicyParser.java b/libcore/security/src/main/java/org/apache/harmony/security/fortress/DefaultPolicyParser.java
index fafa66c..c809fe4 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/fortress/DefaultPolicyParser.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/fortress/DefaultPolicyParser.java
@@ -25,7 +25,6 @@
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.io.File;
import java.io.Reader;
import java.net.URL;
import java.security.cert.Certificate;
@@ -62,8 +61,7 @@
* a pluggable scanner and converts received tokens to a set of
* {@link org.apache.harmony.security.PolicyEntry PolicyEntries}.
* For details of policy format, see the
- * {@link org.apache.harmony.security.fortress.DefaultPolicy default policy
- * description}.
+ * {@link org.apache.harmony.security.DefaultPolicy default policy description}.
* <br>
* For ordinary uses, this class has just one public method <code>parse()</code>,
* which performs the main task.
@@ -73,7 +71,7 @@
* This implementation is effectively thread-safe, as it has no field references
* to data being processed (that is, passes all the data as method parameters).
*
- * @see org.apache.harmony.security.fortress.DefaultPolicy
+ * @see org.apache.harmony.security.DefaultPolicy
* @see org.apache.harmony.security.DefaultPolicyScanner
* @see org.apache.harmony.security.PolicyEntry
*/
@@ -188,7 +186,7 @@
* of the GrantEntry
* @see DefaultPolicyScanner.PrincipalEntry
* @see DefaultPolicyScanner.PermissionEntry
- * @see org.apache.harmony.security.fortress.PolicyUtils
+ * @see org.apache.harmony.security.PolicyUtils
*/
protected PolicyEntry resolveGrant(DefaultPolicyScanner.GrantEntry ge,
KeyStore ks, Properties system, boolean resolve) throws Exception {
@@ -200,14 +198,6 @@
if (ge.codebase != null) {
codebase = new URL(resolve ? PolicyUtils.expandURL(ge.codebase,
system) : ge.codebase);
- //Fix HARMONY-1963
- if ("file".equals(codebase.getProtocol())) { //$NON-NLS-1$
- File codeFile = new File(codebase.getFile());
- if (codeFile.isAbsolute()) {
- codebase = new URL("file://" + //$NON-NLS-1$
- codeFile.getAbsolutePath());
- }
- }
}
if (ge.signers != null) {
if (resolve) {
@@ -342,7 +332,7 @@
if ("self".equals(protocol)) { //$NON-NLS-1$
//need expanding to list of principals in grant clause
if (ge.principals != null && ge.principals.size() != 0) {
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
for (Iterator<PrincipalEntry> iter = ge.principals.iterator(); iter
.hasNext();) {
DefaultPolicyScanner.PrincipalEntry pr = iter
@@ -385,7 +375,7 @@
private String pc2str(Principal pc) {
String klass = pc.getClass().getName();
String name = pc.getName();
- StringBuffer sb = new StringBuffer(klass.length() + name.length()
+ StringBuilder sb = new StringBuilder(klass.length() + name.length()
+ 5);
return sb.append(klass).append(" \"").append(name).append("\"") //$NON-NLS-1$ //$NON-NLS-2$
.toString();
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/fortress/Engine.java b/libcore/security/src/main/java/org/apache/harmony/security/fortress/Engine.java
index 3b6f5d5..19fed41 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/fortress/Engine.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/fortress/Engine.java
@@ -25,6 +25,7 @@
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
+import org.apache.harmony.security.Util;
import org.apache.harmony.security.internal.nls.Messages;
@@ -89,7 +90,7 @@
}
Services.refresh();
if (returnedService != null
- && algorithm.equalsIgnoreCase(lastAlgorithm)
+ && Util.equalsIgnoreCase(algorithm, lastAlgorithm)
&& refreshNumber == Services.refreshNumber) {
serv = returnedService;
} else {
@@ -97,9 +98,9 @@
throw new NoSuchAlgorithmException(Messages.getString("security.14A", //$NON-NLS-1$
serviceName, algorithm));
}
- serv = Services.getService(new StringBuffer(128)
+ serv = Services.getService(new StringBuilder(128)
.append(serviceName).append(".").append( //$NON-NLS-1$
- algorithm.toUpperCase()).toString());
+ Util.toUpperCase(algorithm)).toString());
if (serv == null) {
throw new NoSuchAlgorithmException(Messages.getString("security.14A", //$NON-NLS-1$
serviceName, algorithm));
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/fortress/PolicyUtils.java b/libcore/security/src/main/java/org/apache/harmony/security/fortress/PolicyUtils.java
index eda7327..b4e0e6a 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/fortress/PolicyUtils.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/fortress/PolicyUtils.java
@@ -25,6 +25,8 @@
import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Constructor;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.net.URL;
import java.security.AccessController;
import java.security.Permission;
@@ -39,6 +41,7 @@
import java.util.List;
import java.util.Properties;
+import org.apache.harmony.security.Util;
import org.apache.harmony.security.internal.nls.Messages;
/**
@@ -282,6 +285,56 @@
throws ExpansionFailedException {
return expand(str, properties).replace(File.separatorChar, '/');
}
+
+ /**
+ * Normalizes URLs to standard ones, eliminating pathname symbols.
+ *
+ * @param codebase -
+ * the original URL.
+ * @return - the normalized URL.
+ */
+ public static URL normalizeURL(URL codebase) {
+ if (codebase != null && "file".equals(codebase.getProtocol())) { //$NON-NLS-1$
+ try {
+ if (codebase.getHost().length() == 0) {
+ String path = codebase.getFile();
+
+ if (path.length() == 0) {
+ // codebase is "file:"
+ path = "*";
+ }
+ return filePathToURI(new File(path)
+ .getAbsolutePath()).normalize().toURL();
+ } else {
+ // codebase is "file://<smth>"
+ return codebase.toURI().normalize().toURL();
+ }
+ } catch (Exception e) {
+ // Ignore
+ }
+ }
+ return codebase;
+ }
+
+ /**
+ * Converts a file path to URI without accessing file system
+ * (like {File#toURI()} does).
+ *
+ * @param path -
+ * file path.
+ * @return - the resulting URI.
+ * @throw URISyntaxException
+ */
+ public static URI filePathToURI(String path) throws URISyntaxException {
+ path = path.replace(File.separatorChar, '/');
+
+ if (!path.startsWith("/")) { //$NON-NLS-1$
+ return new URI("file", null, //$NON-NLS-1$
+ new StringBuilder(path.length() + 1).append('/')
+ .append(path).toString(), null, null);
+ }
+ return new URI("file", null, path, null, null); //$NON-NLS-1$
+ }
/**
* Instances of this interface are intended for resolving
@@ -371,7 +424,7 @@
* @see #expand(String, Properties)
*/
public static boolean canExpandProperties() {
- return !FALSE.equalsIgnoreCase(AccessController
+ return !Util.equalsIgnoreCase(FALSE,AccessController
.doPrivileged(new SecurityPropertyAccessor(POLICY_EXPAND)));
}
@@ -417,7 +470,7 @@
URL dynamicURL = null;
//first check if policy is set via system properties
- if (!FALSE.equalsIgnoreCase(AccessController
+ if (!Util.equalsIgnoreCase(FALSE, AccessController
.doPrivileged(security.key(POLICY_ALLOW_DYNAMIC)))) {
String location = system.getProperty(systemUrlKey);
if (location != null) {
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/fortress/Services.java b/libcore/security/src/main/java/org/apache/harmony/security/fortress/Services.java
index 300854a..60d9edd 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/fortress/Services.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/fortress/Services.java
@@ -33,6 +33,8 @@
import java.util.Map;
import java.util.Set;
+import org.apache.harmony.security.Util;
+
/**
* This class contains information about all registered providers and preferred
@@ -56,7 +58,7 @@
/**
* Refresh number
*/
- public static int refreshNumber = 1;
+ static int refreshNumber = 1;
// Registered providers
private static final List<Provider> providers = new ArrayList<Provider>(20);
@@ -89,8 +91,10 @@
providers.add(p);
providersNames.put(p.getName(), p);
initServiceInfo(p);
- } catch (Exception e) { // ignore
- }
+ } catch (ClassNotFoundException e) { // ignore Exceptions
+ } catch (IllegalAccessException e) {
+ } catch (InstantiationException e) {
+ }
}
Engine.door.renumProviders();
}
@@ -166,21 +170,21 @@
String key;
String type;
String alias;
- StringBuffer sb = new StringBuffer(128);
+ StringBuilder sb = new StringBuilder(128);
for (Iterator<Provider.Service> it1 = p.getServices().iterator(); it1.hasNext();) {
serv = it1.next();
type = serv.getType();
sb.delete(0, sb.length());
key = sb.append(type).append(".").append( //$NON-NLS-1$
- serv.getAlgorithm().toUpperCase()).toString();
+ Util.toUpperCase(serv.getAlgorithm())).toString();
if (!services.containsKey(key)) {
services.put(key, serv);
}
for (Iterator<String> it2 = Engine.door.getAliases(serv); it2.hasNext();) {
alias = it2.next();
sb.delete(0, sb.length());
- key = sb.append(type).append(".").append(alias.toUpperCase()) //$NON-NLS-1$
+ key = sb.append(type).append(".").append(Util.toUpperCase(alias)) //$NON-NLS-1$
.toString();
if (!services.containsKey(key)) {
services.put(key, serv);
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/pkcs10/CertificationRequestInfo.java b/libcore/security/src/main/java/org/apache/harmony/security/pkcs10/CertificationRequestInfo.java
index 7c57e93..2f31131 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/pkcs10/CertificationRequestInfo.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/pkcs10/CertificationRequestInfo.java
@@ -115,7 +115,7 @@
public String toString() {
- StringBuffer res = new StringBuffer();
+ StringBuilder res = new StringBuilder();
res.append("-- CertificationRequestInfo:"); //$NON-NLS-1$
res.append("\n version: "); //$NON-NLS-1$
res.append(version);
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/pkcs7/ContentInfo.java b/libcore/security/src/main/java/org/apache/harmony/security/pkcs7/ContentInfo.java
index 0249055..2c129e2 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/pkcs7/ContentInfo.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/pkcs7/ContentInfo.java
@@ -93,7 +93,7 @@
}
public String toString() {
- StringBuffer res = new StringBuffer();
+ StringBuilder res = new StringBuilder();
res.append("==== ContentInfo:"); //$NON-NLS-1$
res.append("\n== ContentType (OID): "); //$NON-NLS-1$
for (int i = 0; i< oid.length; i++) {
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/pkcs7/SignedData.java b/libcore/security/src/main/java/org/apache/harmony/security/pkcs7/SignedData.java
index 718d3d3..2f9e99d 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/pkcs7/SignedData.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/pkcs7/SignedData.java
@@ -105,7 +105,7 @@
}
public String toString() {
- StringBuffer res = new StringBuffer();
+ StringBuilder res = new StringBuilder();
res.append("---- SignedData:"); //$NON-NLS-1$
res.append("\nversion: "); //$NON-NLS-1$
res.append(version);
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/pkcs7/SignerInfo.java b/libcore/security/src/main/java/org/apache/harmony/security/pkcs7/SignerInfo.java
index 05a0c7a..9235577 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/pkcs7/SignerInfo.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/pkcs7/SignerInfo.java
@@ -130,7 +130,7 @@
public String toString() {
- StringBuffer res = new StringBuffer();
+ StringBuilder res = new StringBuilder();
res.append("-- SignerInfo:"); //$NON-NLS-1$
res.append("\n version : "); //$NON-NLS-1$
res.append(version);
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/provider/cert/X509CRLImpl.java b/libcore/security/src/main/java/org/apache/harmony/security/provider/cert/X509CRLImpl.java
index d53eb8a..7414e75 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/provider/cert/X509CRLImpl.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/provider/cert/X509CRLImpl.java
@@ -201,7 +201,7 @@
* from the TBSCertList structure and converts them to the
* X509CRLEntryImpl objects
*/
- private void retirieveEntries() {
+ private void retrieveEntries() {
entriesRetrieved = true;
List rcerts = tbsCertList.getRevokedCertificates();
if (rcerts == null) {
@@ -243,7 +243,7 @@
throw new NullPointerException();
}
if (!entriesRetrieved) {
- retirieveEntries();
+ retrieveEntries();
}
if (entries == null) {
return null;
@@ -295,7 +295,7 @@
*/
public X509CRLEntry getRevokedCertificate(BigInteger serialNumber) {
if (!entriesRetrieved) {
- retirieveEntries();
+ retrieveEntries();
}
if (entries == null) {
return null;
@@ -315,7 +315,7 @@
*/
public Set<? extends X509CRLEntry> getRevokedCertificates() {
if (!entriesRetrieved) {
- retirieveEntries();
+ retrieveEntries();
}
if (entries == null) {
return null;
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java b/libcore/security/src/main/java/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java
index 17fd6f7..f0e47d9 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java
@@ -25,6 +25,7 @@
import java.io.IOException;
import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
import java.security.cert.CRL;
import java.security.cert.CRLException;
import java.security.cert.CertPath;
@@ -446,8 +447,8 @@
// ------------------------ Staff methods ------------------------------
// ---------------------------------------------------------------------
- private static byte[] pemBegin = "-----BEGIN".getBytes(); //$NON-NLS-1$
- private static byte[] pemClose = "-----END".getBytes(); //$NON-NLS-1$
+ private static byte[] pemBegin;
+ private static byte[] pemClose;
/**
* Code describing free format for PEM boundary suffix:
* "^-----BEGIN.*\n" at the beginning, and<br>
@@ -459,8 +460,18 @@
* "^-----BEGIN CERTIFICATE-----\n" at the beginning, and<br>
* "\n-----END CERTIFICATE-----" at the end.
*/
- private static byte[] CERT_BOUND_SUFFIX =
- " CERTIFICATE-----".getBytes(); //$NON-NLS-1$
+ private static byte[] CERT_BOUND_SUFFIX;
+
+ static {
+ // Initialise statics
+ try {
+ pemBegin = "-----BEGIN".getBytes("UTF-8"); //$NON-NLS-1$ //$NON-NLS-2$
+ pemClose = "-----END".getBytes("UTF-8"); //$NON-NLS-1$ //$NON-NLS-2$
+ CERT_BOUND_SUFFIX = " CERTIFICATE-----".getBytes("UTF-8"); //$NON-NLS-1$ //$NON-NLS-2$
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e.getMessage());
+ }
+ }
/**
* Method retrieves the PEM encoded data from the stream
@@ -515,9 +526,7 @@
if (boundary_suffix[i] != inStream.read()) {
throw new IOException(
Messages.getString("security.15B", //$NON-NLS-1$
- ((boundary_suffix == null)
- ? ""
- : new String(boundary_suffix)))); //$NON-NLS-1$
+ new String(boundary_suffix))); //$NON-NLS-1$
}
}
// read new line characters
@@ -574,9 +583,7 @@
if (boundary_suffix[i] != inStream.read()) {
throw new IOException(
Messages.getString("security.15B1", //$NON-NLS-1$
- ((boundary_suffix == null)
- ? ""
- : new String(boundary_suffix)))); //$NON-NLS-1$
+ new String(boundary_suffix))); //$NON-NLS-1$
}
}
}
@@ -933,3 +940,5 @@
}
}
+
+
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/provider/cert/X509CertPathImpl.java b/libcore/security/src/main/java/org/apache/harmony/security/provider/cert/X509CertPathImpl.java
index 2234ce4..83b9944 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/provider/cert/X509CertPathImpl.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/provider/cert/X509CertPathImpl.java
@@ -313,7 +313,7 @@
/**
* ASN.1 DER Encoder/Decoder for PkiPath structure.
*/
- public static ASN1SequenceOf ASN1 =
+ public static final ASN1SequenceOf ASN1 =
new ASN1SequenceOf(ASN1Any.getInstance()) {
/**
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAKeyFactoryImpl.java b/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAKeyFactoryImpl.java
index af314ef..42d3043 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAKeyFactoryImpl.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAKeyFactoryImpl.java
@@ -38,7 +38,7 @@
public class DSAKeyFactoryImpl extends KeyFactorySpi {
/**
- * The method generates a DSAPrivateKey object from the provided key specification.
+ * This method generates a DSAPrivateKey object from the provided key specification.
*
* @param
* keySpec - the specification (key material) for the DSAPrivateKey.
@@ -66,7 +66,7 @@
}
/**
- * The method generates a DSAPublicKey object from the provided key specification.
+ * This method generates a DSAPublicKey object from the provided key specification.
*
* @param
* keySpec - the specification (key material) for the DSAPublicKey.
@@ -92,28 +92,23 @@
}
throw new InvalidKeySpecException(Messages.getString("security.19D")); //$NON-NLS-1$
}
-
+
/**
- * The method returns a specification (key material) of the given key object.
- * 'keySpec' identifies the specification class
- * in which the key material should be returned.
- *
- * If it is DSAPublicKeySpec.class, the key material should be returned
- * in an instance of the DSAPublicKeySpec class;
- * if it is DSAPrivateKeySpec.class, the key material should be returned
- * in an instance of the DSAPrivateKeySpec class.
- *
- * @param
- * key - either DSAPrivateKey or DSAPublicKey
- * @param
- * keySpec - either DSAPublicKeySpec.class or DSAPublicKeySpec.class
- *
- * @return
- * either DSAPublicKeySpec object or DSAPublicKeySpec object
- *
+ * This method returns a specification for the supplied key.
+ *
+ * The specification will be returned in the form of an object of the type
+ * specified by keySpec.
+ *
+ * @param key -
+ * either DSAPrivateKey or DSAPublicKey
+ * @param keySpec -
+ * either DSAPrivateKeySpec.class or DSAPublicKeySpec.class
+ *
+ * @return either a DSAPrivateKeySpec or a DSAPublicKeySpec
+ *
* @throws InvalidKeySpecException
- * if "keySpec" is not s specification for DSAPublicKey or DSAPrivateKey
- *
+ * if "keySpec" is not a specification for DSAPublicKey or
+ * DSAPrivateKey
*/
protected <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec)
throws InvalidKeySpecException {
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAPrivateKeyImpl.java b/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAPrivateKeyImpl.java
index 17af038..291d69e 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAPrivateKeyImpl.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAPrivateKeyImpl.java
@@ -27,6 +27,7 @@
package org.apache.harmony.security.provider.crypto;
import java.io.IOException;
+import java.io.NotActiveException;
import java.math.BigInteger;
import java.security.interfaces.DSAParams;
import java.security.interfaces.DSAPrivateKey;
@@ -53,9 +54,9 @@
*/
private static final long serialVersionUID = -4716227614104950081L;
- private BigInteger x;
+ private BigInteger x, g, p, q;
- private DSAParams params;
+ private transient DSAParams params;
/**
* Creates object from DSAPrivateKeySpec.
@@ -68,9 +69,9 @@
PrivateKeyInfo pki;
- BigInteger g = keySpec.getG();
- BigInteger p = keySpec.getP();
- BigInteger q = keySpec.getQ();
+ g = keySpec.getG();
+ p = keySpec.getP();
+ q = keySpec.getQ();
ThreeIntegerSequence threeInts = new ThreeIntegerSequence(p
.toByteArray(), q.toByteArray(), g.toByteArray());
@@ -133,9 +134,10 @@
throw new InvalidKeySpecException(Messages.getString(
"security.19B", e)); //$NON-NLS-1$
}
- params = new DSAParameterSpec(new BigInteger(threeInts.p),
- new BigInteger(threeInts.q), new BigInteger(threeInts.g));
-
+ p = new BigInteger(threeInts.p);
+ q = new BigInteger(threeInts.q);
+ g = new BigInteger(threeInts.g);
+ params = new DSAParameterSpec(p, q, g);
setEncoding(encoding);
/*
@@ -153,5 +155,10 @@
public DSAParams getParams() {
return params;
}
+
+ private void readObject(java.io.ObjectInputStream in) throws NotActiveException, IOException, ClassNotFoundException {
+ in.defaultReadObject();
+ params = new DSAParameterSpec(p, q, g);
+ }
}
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAPublicKeyImpl.java b/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAPublicKeyImpl.java
index bd1efdd..f4bb13d 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAPublicKeyImpl.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/DSAPublicKeyImpl.java
@@ -29,6 +29,7 @@
package org.apache.harmony.security.provider.crypto;
import java.io.IOException;
+import java.io.NotActiveException;
import java.math.BigInteger;
@@ -45,12 +46,6 @@
import org.apache.harmony.security.x509.SubjectPublicKeyInfo;
import org.apache.harmony.security.asn1.ASN1Integer;
-//import org.apache.harmony.security.asn1.ASN1Sequence;
-//import org.apache.harmony.security.asn1.ASN1Type;
-//import org.apache.harmony.security.asn1.BerInputStream;
-//import org.apache.harmony.security.asn1.ASN1BitString;
-//import org.apache.harmony.security.asn1.BitString;
-//import org.apache.harmony.security.asn1.ASN1OctetString;
import org.apache.harmony.security.internal.nls.Messages;
@@ -67,9 +62,9 @@
*/
private static final long serialVersionUID = -2279672131310978336L;
- private BigInteger y;
+ private BigInteger y, g, p, q;
- private DSAParams params;
+ private transient DSAParams params;
/**
* Creates object from DSAPublicKeySpec.
@@ -82,9 +77,9 @@
SubjectPublicKeyInfo spki;
- BigInteger p = keySpec.getP();
- BigInteger q = keySpec.getQ();
- BigInteger g = keySpec.getG();
+ p = keySpec.getP();
+ q = keySpec.getQ();
+ g = keySpec.getG();
ThreeIntegerSequence threeInts = new ThreeIntegerSequence(p
.toByteArray(), q.toByteArray(), g.toByteArray());
@@ -148,8 +143,10 @@
throw new InvalidKeySpecException(Messages.getString(
"security.19B", e)); //$NON-NLS-1$
}
- params = (DSAParams) (new DSAParameterSpec(new BigInteger(threeInts.p),
- new BigInteger(threeInts.q), new BigInteger(threeInts.g)));
+ p = new BigInteger(threeInts.p);
+ q = new BigInteger(threeInts.q);
+ g = new BigInteger(threeInts.g);
+ params = (DSAParams) (new DSAParameterSpec(p, q, g));
setEncoding(encoding);
@@ -176,5 +173,10 @@
public DSAParams getParams() {
return params;
}
+
+ private void readObject(java.io.ObjectInputStream in) throws NotActiveException, IOException, ClassNotFoundException {
+ in.defaultReadObject();
+ params = new DSAParameterSpec(p, q, g);
+ }
}
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/RandomBitsSupplier.java b/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/RandomBitsSupplier.java
index 14db652..e3fde7f 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/RandomBitsSupplier.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/RandomBitsSupplier.java
@@ -35,7 +35,7 @@
* The static class providing access on Linux platform
* to system means for generating true random bits. <BR>
*
- * The source for true random bits is one of Linux's devices "/dev/urandom/" or
+ * The source for true random bits is one of Linux's devices "/dev/urandom" or
* "/dev/random" depends on which one is available; if both the first is used. <BR>
*
* If no device available the service is not available,
@@ -69,7 +69,7 @@
/**
* value of field is "true" only if a device is available
*/
- private static boolean serviceAvailable;
+ private static boolean serviceAvailable = false;
static {
@@ -86,16 +86,26 @@
bis = new FileInputStream(file);
// END android-modified
randomFile = file;
+ serviceAvailable = true;
return null;
}
} catch (FileNotFoundException e) {
}
}
+
+ // BEGIN android-removed
+// // If we have come out of the above loop, then we have been unable to
+// // access /dev/*random, so try to fall back to using the system random() API
+// try {
+// System.loadLibrary(LIBRARY_NAME);
+// serviceAvailable = true;
+// } catch (UnsatisfiedLinkError e) {
+// serviceAvailable = false;
+// }
return null;
}
}
);
- serviceAvailable = (bis != null);
}
@@ -108,12 +118,12 @@
/**
- * On the Linux platform with "random" devices available,
+ * On platforms with "random" devices available,
* the method reads random bytes from the device. <BR>
*
* In case of any runtime failure ProviderException gets thrown.
*/
- private static synchronized byte[] getLinuxRandomBits(int numBytes) {
+ private static synchronized byte[] getUnixDeviceRandom(int numBytes) {
byte[] bytes = new byte[numBytes];
@@ -128,7 +138,6 @@
// the below case should not occur because /dev/random or /dev/urandom is a special file
// hence, if it is happened there is some internal problem
- //
if ( bytesRead == -1 ) {
throw new ProviderException(
Messages.getString("security.193") ); //$NON-NLS-1$
@@ -146,7 +155,6 @@
// actually there should be no IOException because device is a special file;
// hence, there is either some internal problem or, for instance,
// device was removed in runtime, or something else
- //
throw new ProviderException(
Messages.getString("security.194"), e ); //$NON-NLS-1$
}
@@ -154,6 +162,17 @@
}
+ // BEGIN android-removed
+// /**
+// * On platforms with no "random" devices available, this native
+// * method uses system API calls to generate random numbers<BR>
+// *
+// * In case of any runtime failure ProviderException gets thrown.
+// */
+// private static native synchronized boolean getUnixSystemRandom(byte[] randomBits, int numBytes);
+ // END android-removed
+
+
/**
* The method returns byte array of requested length provided service is available.
* ProviderException gets thrown otherwise.
@@ -171,12 +190,15 @@
throw new IllegalArgumentException(Messages.getString("security.195", numBytes)); //$NON-NLS-1$
}
+ // We have been unable to get a random device or fall back to the
+ // native security module code - throw an exception.
if ( !serviceAvailable ) {
throw new ProviderException(
Messages.getString("security.196")); //$NON-NLS-1$
}
- return getLinuxRandomBits(numBytes);
+ // BEGIN android-changed
+ return getUnixDeviceRandom(numBytes);
+ // END android-changed
}
-
}
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_Data.java b/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_Data.java
index 6e9ecb8..7294361 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_Data.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_Data.java
@@ -82,10 +82,12 @@
static final int DIGEST_LENGTH = 20;
- /**
- * name of native library to use on Windows platform
- */
- static final String LIBRARY_NAME = "hysecurity"; //$NON-NLS-1$
+ // BEGIN android-removed
+// /**
+// * name of native library to use on Windows platform
+// */
+// static final String LIBRARY_NAME = "hysecurity"; //$NON-NLS-1$
+ // END android-removed
/**
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/SHA1withDSA_SignatureImpl.java b/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/SHA1withDSA_SignatureImpl.java
index 576ac76..b7b9c98 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/SHA1withDSA_SignatureImpl.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/provider/crypto/SHA1withDSA_SignatureImpl.java
@@ -83,7 +83,7 @@
DSAParams params;
// parameters and private key
- BigInteger p, q, g, x;
+ BigInteger p, q, x;
int n;
@@ -95,7 +95,6 @@
params = ((DSAPrivateKey) privateKey).getParams();
p = params.getP();
q = params.getQ();
- g = params.getG();
x = ((DSAPrivateKey) privateKey).getX();
// checks described in DSA standard
@@ -129,7 +128,7 @@
throws InvalidKeyException {
// parameters and public key
- BigInteger p, q, g, y;
+ BigInteger p, q, y;
int n1;
@@ -141,7 +140,6 @@
DSAParams params = ((DSAPublicKey) publicKey).getParams();
p = params.getP();
q = params.getQ();
- g = params.getG();
y = ((DSAPublicKey) publicKey).getY();
// checks described in DSA standard
@@ -207,7 +205,6 @@
// various byte array being used in computing signature
byte randomBytes[];
- byte digest[];
byte rBytes[], sBytes[], signature[];
int n, n1, n2;
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java b/libcore/security/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java
index f1f5bce..bc84c01 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java
@@ -29,43 +29,13 @@
import java.util.Set;
import java.util.Map.Entry;
+import org.apache.harmony.security.Util;
import org.apache.harmony.security.asn1.ObjectIdentifier;
/**
- * Provides Algorithm Name to OID
- * and OID to Algorithm Name mappings.
- * Some known mappings are hardcoded.
- * Tries to obtain additional mappings
- * from installed providers during initialization.
- *
- * Hardcoded mappings
- * (source: http://asn1.elibel.tm.fr):
- *
- * 1.2.840.10040.4.1 -> DSA
- *
- * 1.2.840.113549.1.1.1 -> RSA
- *
- * 1.2.840.113549.1.3.1 -> DiffieHellman
- *
- * 1.2.840.113549.1.5.3 -> PBEWithMD5AndDES
- *
- * 1.2.840.113549.1.12.1.3 -> pbeWithSHAAnd3-KeyTripleDES-CBC
- * 1.2.840.113549.1.12.1.3 -> PBEWithSHA1AndDESede
- * 1.2.840.113549.1.12.1.3 -> PBEWithSHA1AndTripleDES
- *
- * 1.2.840.113549.1.12.1.6 -> pbeWithSHAAnd40BitRC2-CBC
- * 1.2.840.113549.1.12.1.6 -> PBEWithSHA1AndRC2_40
- *
- * 1.2.840.113549.3.2 -> RC2-CBC
- * 1.2.840.113549.3.3 -> RC2-EBC
- * 1.2.840.113549.3.4 -> RC4
- * 1.2.840.113549.3.5 -> RC4WithMAC
- * 1.2.840.113549.3.6 -> DESx-CBC
- * 1.2.840.113549.3.7 -> TripleDES-CBC
- * 1.2.840.113549.3.8 -> rc5CBC
- * 1.2.840.113549.3.9 -> RC5-CBC
- * 1.2.840.113549.3.10 -> DESCDMF (CDMFCBCPad)
- *
+ * Provides Algorithm Name to OID and OID to Algorithm Name mappings. Some known
+ * mappings are hardcoded. Tries to obtain additional mappings from installed
+ * providers during initialization.
*/
public class AlgNameMapper {
@@ -114,7 +84,7 @@
static {
for (String[] element : knownAlgMappings) {
- String algUC = element[1].toUpperCase();
+ String algUC = Util.toUpperCase(element[1]);
alg2OidMap.put(algUC, element[0]);
oid2AlgMap.put(element[0], algUC);
// map upper case alg name to its original name
@@ -144,7 +114,7 @@
*/
public static String map2OID(String algName) {
// alg2OidMap map contains upper case keys
- return alg2OidMap.get(algName.toUpperCase());
+ return alg2OidMap.get(Util.toUpperCase(algName));
}
/**
@@ -167,7 +137,7 @@
* @return algorithm name
*/
public static String getStandardName(String algName) {
- return algAliasesMap.get(algName.toUpperCase());
+ return algAliasesMap.get(Util.toUpperCase(algName));
}
// Searches given provider for mappings like
@@ -184,7 +154,7 @@
if (key.startsWith(keyPrfix2find)) {
String alias = key.substring(keyPrfix2find.length());
String alg = (String)me.getValue();
- String algUC = alg.toUpperCase();
+ String algUC = Util.toUpperCase(alg);
if (isOID(alias)) {
if (alias.startsWith("OID.")) { //$NON-NLS-1$
alias = alias.substring(4);
@@ -203,8 +173,8 @@
algAliasesMap.put(algUC, alg);
}
// Do not override known standard names
- } else if (!algAliasesMap.containsKey(alias.toUpperCase())) {
- algAliasesMap.put(alias.toUpperCase(), alg);
+ } else if (!algAliasesMap.containsKey(Util.toUpperCase(alias))) {
+ algAliasesMap.put(Util.toUpperCase(alias), alg);
}
}
}
@@ -240,7 +210,7 @@
* @return Internal maps String representation
*/
public static String dump() {
- StringBuffer sb = new StringBuffer("alg2OidMap: "); //$NON-NLS-1$
+ StringBuilder sb = new StringBuilder("alg2OidMap: "); //$NON-NLS-1$
sb.append(alg2OidMap);
sb.append("\noid2AlgMap: "); //$NON-NLS-1$
sb.append(oid2AlgMap);
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/utils/ObjectIdentifier.java b/libcore/security/src/main/java/org/apache/harmony/security/utils/ObjectIdentifier.java
index 517e096..2a19656 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/utils/ObjectIdentifier.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/utils/ObjectIdentifier.java
@@ -158,7 +158,7 @@
*/
public String toString() {
if (soid == null) {
- StringBuffer sb = new StringBuffer(4 * oid.length);
+ StringBuilder sb = new StringBuilder(4 * oid.length);
for (int i = 0; i < oid.length - 1; ++i) {
sb.append(oid[i]);
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValue.java b/libcore/security/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValue.java
index 34337eb..6343489 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValue.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValue.java
@@ -28,6 +28,7 @@
import java.util.Iterator;
import javax.security.auth.x500.X500Principal;
+import java.io.UnsupportedEncodingException;
import org.apache.harmony.security.asn1.ASN1Constants;
import org.apache.harmony.security.asn1.ASN1Oid;
@@ -38,6 +39,7 @@
import org.apache.harmony.security.asn1.BerOutputStream;
import org.apache.harmony.security.internal.nls.Messages;
import org.apache.harmony.security.utils.ObjectIdentifier;
+import org.apache.harmony.security.Util;
/**
@@ -284,7 +286,7 @@
this.oid = thisOid;
} else {
- this.oid = (ObjectIdentifier) KNOWN_NAMES.get(sOid.toUpperCase());
+ this.oid = (ObjectIdentifier) KNOWN_NAMES.get(Util.toUpperCase(sOid));
if (this.oid == null) {
throw new IOException(Messages.getString("security.178", sOid)); //$NON-NLS-1$
}
@@ -301,7 +303,7 @@
public void appendName(String attrFormat, StringBuffer buf) {
boolean hexFormat = false;
- if (attrFormat == X500Principal.RFC1779) {
+ if (X500Principal.RFC1779.equals(attrFormat)) {
if (RFC1779_NAMES == oid.getGroup()) {
buf.append(oid.getName());
} else {
@@ -311,7 +313,7 @@
buf.append('=');
if (value.escapedString == value.getHexString()) {
//FIXME all chars in upper case
- buf.append(value.getHexString().toUpperCase());
+ buf.append(Util.toUpperCase(value.getHexString()));
} else if (value.escapedString.length() != value.rawString.length()) {
// was escaped
value.appendQEString(buf);
@@ -324,7 +326,7 @@
if (RFC1779_NAMES == group || RFC2253_NAMES == group) {
buf.append(oid.getName());
- if (attrFormat == X500Principal.CANONICAL) {
+ if (X500Principal.CANONICAL.equals(attrFormat)) {
// only PrintableString and UTF8String in string format
// all others are output in hex format
// BEGIN android-changed
@@ -348,7 +350,7 @@
if (hexFormat) {
buf.append(value.getHexString());
} else {
- if (attrFormat == X500Principal.CANONICAL) {
+ if (X500Principal.CANONICAL.equals(attrFormat)) {
buf.append(value.makeCanonical());
} else {
buf.append(value.escapedString);
@@ -387,7 +389,7 @@
*
*/
- public static ASN1Type AttributeValue = new ASN1Type(
+ public static final ASN1Type attributeValue = new ASN1Type(
ASN1Constants.TAG_PRINTABLESTRING) {
public boolean checkTag(int tag) {
@@ -452,7 +454,11 @@
av.bytes = (byte[]) out.content;
out.content = av;
} else {
- av.bytes = av.rawString.getBytes();
+ try {
+ av.bytes = av.rawString.getBytes("UTF-8"); //$NON-NLS-1$
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e.getMessage());
+ }
out.length = av.bytes.length;
}
}
@@ -476,7 +482,7 @@
};
public static final ASN1Sequence ASN1 = new ASN1Sequence(new ASN1Type[] {
- ASN1Oid.getInstance(), AttributeValue }) {
+ ASN1Oid.getInstance(), attributeValue }) {
protected Object getDecodedObject(BerInputStream in) throws IOException {
Object[] values = (Object[]) in.content;
@@ -541,4 +547,4 @@
}
return intHash & 0x7FFFFFFF; // only positive
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValueComparator.java b/libcore/security/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValueComparator.java
index 8844035..30d71e7 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValueComparator.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValueComparator.java
@@ -22,6 +22,7 @@
package org.apache.harmony.security.x501;
+import java.io.Serializable;
import java.util.Comparator;
import org.apache.harmony.security.utils.ObjectIdentifier;
@@ -30,9 +31,11 @@
* AttributeTypeAndValue comparator
*
*/
-public class AttributeTypeAndValueComparator implements Comparator {
+public class AttributeTypeAndValueComparator implements Comparator, Serializable {
- /**
+ private static final long serialVersionUID = -1286471842007103132L;
+
+ /**
* compares two AttributeTypeAndValues
*
* @param obj1
@@ -63,14 +66,7 @@
return compateOids(atav1.getType(), atav2.getType());
}
-
- /**
- * @return false
- */
- public boolean equals(Object obj) {
- return false;
- }
-
+
/**
* compares two Object identifiers
*
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x501/AttributeValue.java b/libcore/security/src/main/java/org/apache/harmony/security/x501/AttributeValue.java
index 51f9725..0844c5e 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x501/AttributeValue.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x501/AttributeValue.java
@@ -126,7 +126,7 @@
}
}
- StringBuffer buf = new StringBuffer(encoded.length * 2 + 1);
+ StringBuilder buf = new StringBuilder(encoded.length * 2 + 1);
buf.append('#');
for (int i = 0, c; i < encoded.length; i++) {
@@ -180,7 +180,7 @@
if (length == 0) {
return name;
}
- StringBuffer buf = new StringBuffer(length * 2);
+ StringBuilder buf = new StringBuilder(length * 2);
for (int index = 0; index < length; index++) {
@@ -223,7 +223,7 @@
if (length == 0) {
return rawString;
}
- StringBuffer buf = new StringBuffer(length * 2);
+ StringBuilder buf = new StringBuilder(length * 2);
int index = 0;
if (rawString.charAt(0) == '#') {
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x501/Name.java b/libcore/security/src/main/java/org/apache/harmony/security/x501/Name.java
index 836342e..ae08671 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x501/Name.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x501/Name.java
@@ -118,21 +118,21 @@
//
// check X500Principal constants first
//
- if (format == X500Principal.RFC1779) {
+ if (X500Principal.RFC1779.equals(format)) {
if (rfc1779String == null) {
rfc1779String = getName0(format);
}
return rfc1779String;
- } else if (format == X500Principal.RFC2253) {
+ } else if (X500Principal.RFC2253.equals(format)) {
if (rfc2253String == null) {
rfc2253String = getName0(format);
}
return rfc2253String;
- } else if (format == X500Principal.CANONICAL) {
+ } else if (X500Principal.CANONICAL.equals(format)) {
if (canonicalString == null) {
canonicalString = getName0(format);
@@ -217,7 +217,7 @@
}
String sName = name.toString();
- if (format == X500Principal.CANONICAL) {
+ if (X500Principal.CANONICAL.equals(format)) {
sName = sName.toLowerCase(Locale.US);
}
return sName;
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/AccessDescription.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/AccessDescription.java
index bc8fd28..69b9258 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/AccessDescription.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/AccessDescription.java
@@ -70,7 +70,7 @@
}
public String toString() {
- StringBuffer res = new StringBuffer();
+ StringBuilder res = new StringBuilder();
res.append("\n-- AccessDescription:"); //$NON-NLS-1$
res.append("\naccessMethod: "); //$NON-NLS-1$
res.append(accessMethod);
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/AlgorithmIdentifier.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/AlgorithmIdentifier.java
index 70dba99..728fd6a 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/AlgorithmIdentifier.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/AlgorithmIdentifier.java
@@ -143,6 +143,11 @@
: Arrays.equals(parameters, algid.parameters));
}
+ public int hashCode() {
+ return algorithm.hashCode() * 37 +
+ (parameters != null ? parameters.hashCode() : 0);
+ }
+
/**
* Places the string representation into the StringBuffer object.
*/
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/AuthorityKeyIdentifier.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/AuthorityKeyIdentifier.java
index 1cf9c3e..3de59fb 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/AuthorityKeyIdentifier.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/AuthorityKeyIdentifier.java
@@ -103,7 +103,7 @@
buffer.append(prefix).append("]\n"); //$NON-NLS-1$
}
- public static ASN1Type ASN1 = new ASN1Sequence(
+ public static final ASN1Type ASN1 = new ASN1Sequence(
new ASN1Type[] {
new ASN1Implicit(0, ASN1OctetString.getInstance()),
new ASN1Implicit(1, GeneralNames.ASN1),
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/BasicConstraints.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/BasicConstraints.java
index 10b3156..edbf13e 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/BasicConstraints.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/BasicConstraints.java
@@ -105,7 +105,7 @@
/**
* ASN.1 Encoder/Decoder.
*/
- public static ASN1Type ASN1 = new ASN1Sequence(new ASN1Type[] {
+ public static final ASN1Type ASN1 = new ASN1Sequence(new ASN1Type[] {
ASN1Boolean.getInstance(), ASN1Integer.getInstance() }) {
{
setDefault(Boolean.FALSE, 0);
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/CRLNumber.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/CRLNumber.java
index 85cbea0..db2480e 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/CRLNumber.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/CRLNumber.java
@@ -84,5 +84,5 @@
/**
* ASN.1 Encoder/Decoder.
*/
- public static ASN1Type ASN1 = ASN1Integer.getInstance();
+ public static final ASN1Type ASN1 = ASN1Integer.getInstance();
}
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/CertificateIssuer.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/CertificateIssuer.java
index 3a31734..d6ab760 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/CertificateIssuer.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/CertificateIssuer.java
@@ -87,7 +87,7 @@
/**
* ASN.1 Encoder/Decoder.
*/
- public static ASN1Type ASN1 = new ASN1Sequence(new ASN1Type[] {
+ public static final ASN1Type ASN1 = new ASN1Sequence(new ASN1Type[] {
GeneralName.ASN1
}) {
public Object getDecodedObject(BerInputStream in) {
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/DNParser.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/DNParser.java
index 730f7df..5870bcd 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/DNParser.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/DNParser.java
@@ -293,6 +293,9 @@
case '#':
case ';':
case ' ':
+ case '*':
+ case '%':
+ case '_':
//FIXME: escaping is allowed only for leading or trailing space char
return chars[pos];
default:
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/ExtendedKeyUsage.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/ExtendedKeyUsage.java
index 69e9cee..4eacbd5 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/ExtendedKeyUsage.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/ExtendedKeyUsage.java
@@ -109,7 +109,7 @@
/**
* ASN.1 Encoder/Decoder.
*/
- public static ASN1Type ASN1 =
+ public static final ASN1Type ASN1 =
new ASN1SequenceOf(new ASN1Oid() {
public Object getDecodedObject(BerInputStream in)
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/Extension.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/Extension.java
index 833f2fe..86e7a45 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/Extension.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/Extension.java
@@ -58,34 +58,34 @@
// constants: the extension OIDs
// certificate extensions:
- public static final int[] SUBJ_DIRECTORY_ATTRS = {2, 5, 29, 9};
- public static final int[] SUBJ_KEY_ID = {2, 5, 29, 14};
- public static final int[] KEY_USAGE = {2, 5, 29, 15};
- public static final int[] PRIVATE_KEY_USAGE_PERIOD = {2, 5, 29, 16};
- public static final int[] SUBJECT_ALT_NAME = {2, 5, 29, 17};
- public static final int[] ISSUER_ALTERNATIVE_NAME = {2, 5, 29, 18};
- public static final int[] BASIC_CONSTRAINTS = {2, 5, 29, 19};
- public static final int[] NAME_CONSTRAINTS = {2, 5, 29, 30};
- public static final int[] CRL_DISTR_POINTS = {2, 5, 29, 31};
- public static final int[] CERTIFICATE_POLICIES = {2, 5, 29, 32};
- public static final int[] POLICY_MAPPINGS = {2, 5, 29, 33};
- public static final int[] AUTH_KEY_ID = {2, 5, 29, 35};
- public static final int[] POLICY_CONSTRAINTS = {2, 5, 29, 36};
- public static final int[] EXTENDED_KEY_USAGE = {2, 5, 29, 37};
- public static final int[] FRESHEST_CRL = {2, 5, 29, 46};
- public static final int[] INHIBIT_ANY_POLICY = {2, 5, 29, 54};
- public static final int[] AUTHORITY_INFO_ACCESS =
+ static final int[] SUBJ_DIRECTORY_ATTRS = {2, 5, 29, 9};
+ static final int[] SUBJ_KEY_ID = {2, 5, 29, 14};
+ static final int[] KEY_USAGE = {2, 5, 29, 15};
+ static final int[] PRIVATE_KEY_USAGE_PERIOD = {2, 5, 29, 16};
+ static final int[] SUBJECT_ALT_NAME = {2, 5, 29, 17};
+ static final int[] ISSUER_ALTERNATIVE_NAME = {2, 5, 29, 18};
+ static final int[] BASIC_CONSTRAINTS = {2, 5, 29, 19};
+ static final int[] NAME_CONSTRAINTS = {2, 5, 29, 30};
+ static final int[] CRL_DISTR_POINTS = {2, 5, 29, 31};
+ static final int[] CERTIFICATE_POLICIES = {2, 5, 29, 32};
+ static final int[] POLICY_MAPPINGS = {2, 5, 29, 33};
+ static final int[] AUTH_KEY_ID = {2, 5, 29, 35};
+ static final int[] POLICY_CONSTRAINTS = {2, 5, 29, 36};
+ static final int[] EXTENDED_KEY_USAGE = {2, 5, 29, 37};
+ static final int[] FRESHEST_CRL = {2, 5, 29, 46};
+ static final int[] INHIBIT_ANY_POLICY = {2, 5, 29, 54};
+ static final int[] AUTHORITY_INFO_ACCESS =
{1, 3, 6, 1, 5, 5, 7, 1, 1};
- public static final int[] SUBJECT_INFO_ACCESS =
+ static final int[] SUBJECT_INFO_ACCESS =
{1, 3, 6, 1, 5, 5, 7, 1, 11};
// crl extensions:
- public static final int[] ISSUING_DISTR_POINT = {2, 5, 29, 28};
+ static final int[] ISSUING_DISTR_POINT = {2, 5, 29, 28};
// crl entry extensions:
- public static final int[] CRL_NUMBER = {2, 5, 29, 20};
- public static final int[] CERTIFICATE_ISSUER = {2, 5, 29, 29};
- public static final int[] INVALIDITY_DATE = {2, 5, 29, 24};
- public static final int[] REASON_CODE = {2, 5, 29, 21};
- public static final int[] ISSUING_DISTR_POINTS = {2, 5, 29, 28};
+ static final int[] CRL_NUMBER = {2, 5, 29, 20};
+ static final int[] CERTIFICATE_ISSUER = {2, 5, 29, 29};
+ static final int[] INVALIDITY_DATE = {2, 5, 29, 24};
+ static final int[] REASON_CODE = {2, 5, 29, 21};
+ static final int[] ISSUING_DISTR_POINTS = {2, 5, 29, 28};
// the value of extnID field of the structure
private final int[] extnID;
@@ -238,6 +238,10 @@
&& (critical == extn.critical)
&& Arrays.equals(extnValue, extn.extnValue);
}
+
+ public int hashCode() {
+ return (extnID.hashCode() * 37 + (critical ? 1 : 0)) * 37 + extnValue.hashCode();
+ }
public ExtensionValue getDecodedExtensionValue() throws IOException {
if (!valueDecoded) {
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/Extensions.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/Extensions.java
index e98a116..1fee6c0 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/Extensions.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/Extensions.java
@@ -386,6 +386,14 @@
);
}
+ public int hashCode() {
+ int hashcode = 0;
+ if (extensions != null) {
+ hashcode = extensions.hashCode();
+ }
+ return hashcode;
+ }
+
/**
* Places the string representation into the StringBuffer object.
*/
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/GeneralName.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/GeneralName.java
index db4daaa..3b291a1 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/GeneralName.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/GeneralName.java
@@ -328,6 +328,24 @@
return false;
}
+ public int hashCode() {
+ switch(tag) {
+ case RFC822_NAME:
+ case DNS_NAME:
+ case UR_ID:
+ case REG_ID:
+ case IP_ADDR:
+ return name.hashCode();
+ case DIR_NAME:
+ case X400_ADDR:
+ case OTHER_NAME:
+ case EDIP_NAME:
+ return getEncoded().hashCode();
+ default:
+ return super.hashCode();
+ }
+ }
+
/**
* Checks if the other general name is acceptable by this object.
* The name is acceptable if it has the same type name and its
@@ -562,16 +580,21 @@
/**
* Checks the correctness of the string representation of DNS name.
- * The correctness is checked as specified in RFC 1034 p. 10.
+ * The correctness is checked as specified in RFC 1034 p. 10, and modified
+ * by RFC 1123 (section 2.1).
*/
public static void checkDNS(String dns) throws IOException {
- byte[] bytes = dns.toLowerCase().getBytes();
+ byte[] bytes = dns.toLowerCase().getBytes("UTF-8"); //$NON-NLS-1$
// indicates if it is a first letter of the label
boolean first_letter = true;
for (int i=0; i<bytes.length; i++) {
byte ch = bytes[i];
if (first_letter) {
- if (ch > 'z' || ch < 'a') {
+ if ((bytes.length > 2) && (ch == '*') && (bytes[1] == '.')) {
+ first_letter = false;
+ continue;
+ }
+ if ((ch > 'z' || ch < 'a') && (ch < '0' || ch > '9')) {
throw new IOException(Messages.getString("security.184", //$NON-NLS-1$
(char)ch, dns));
}
@@ -585,7 +608,7 @@
if (ch == '.') {
// check the end of the previous label, it should not
// be '-' sign
- if (bytes[i-i] == '-') {
+ if (bytes[i-1] == '-') {
throw new IOException(
Messages.getString("security.186", dns)); //$NON-NLS-1$
}
@@ -619,7 +642,7 @@
* Converts OID into array of bytes.
*/
public static int[] oidStrToInts(String oid) throws IOException {
- byte[] bytes = oid.getBytes();
+ byte[] bytes = oid.getBytes("UTF-8"); //$NON-NLS-1$
if (bytes[bytes.length-1] == '.') {
throw new IOException(Messages.getString("security.56", oid)); //$NON-NLS-1$
}
@@ -673,7 +696,7 @@
}
// the resulting array
byte[] result = new byte[num_components];
- byte[] ip_bytes = ip.getBytes();
+ byte[] ip_bytes = ip.getBytes("UTF-8"); //$NON-NLS-1$
// number of address component to be read
int component = 0;
// if it is reading the second bound of a range
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/InfoAccessSyntax.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/InfoAccessSyntax.java
index 7323124..ce5404e 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/InfoAccessSyntax.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/InfoAccessSyntax.java
@@ -86,7 +86,7 @@
}
public String toString() {
- StringBuffer res = new StringBuffer();
+ StringBuilder res = new StringBuilder();
res.append("\n---- InfoAccessSyntax:"); //$NON-NLS-1$
if (accessDescriptions != null) {
for (Iterator it = accessDescriptions.iterator(); it.hasNext();) {
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/InvalidityDate.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/InvalidityDate.java
index bc04caf..b01fa45 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/InvalidityDate.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/InvalidityDate.java
@@ -82,6 +82,6 @@
/**
* ASN.1 Encoder/Decoder.
*/
- public static ASN1Type ASN1 = ASN1GeneralizedTime.getInstance();
+ public static final ASN1Type ASN1 = ASN1GeneralizedTime.getInstance();
}
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/IssuingDistributionPoint.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/IssuingDistributionPoint.java
index aec57c3..102fe05 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/IssuingDistributionPoint.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/IssuingDistributionPoint.java
@@ -180,7 +180,7 @@
/**
* ASN.1 Encoder/Decoder.
*/
- public static ASN1Type ASN1 = new ASN1Sequence(
+ public static final ASN1Type ASN1 = new ASN1Sequence(
new ASN1Type[] {
// ASN.1 prohibits implicitly tagged CHOICE
new ASN1Explicit(0, DistributionPointName.ASN1),
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/ReasonCode.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/ReasonCode.java
index 26b4acc..de3505d 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/ReasonCode.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/ReasonCode.java
@@ -128,6 +128,6 @@
/**
* ASN.1 Encoder/Decoder.
*/
- public static ASN1Type ASN1 = ASN1Enumerated.getInstance();
+ public static final ASN1Type ASN1 = ASN1Enumerated.getInstance();
}
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/ReasonFlags.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/ReasonFlags.java
index 6f72dc7..842784f 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/ReasonFlags.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/ReasonFlags.java
@@ -55,7 +55,7 @@
/**
* The names of the reasons.
*/
- public static final String[] REASONS = {
+ static final String[] REASONS = {
"unused", //$NON-NLS-1$
"keyCompromise", //$NON-NLS-1$
"cACompromise", //$NON-NLS-1$
@@ -97,7 +97,7 @@
/**
* ASN.1 Encoder/Decoder.
*/
- public static ASN1BitString ASN1 =
+ public static final ASN1BitString ASN1 =
new ASN1BitString.ASN1NamedBitList(REASONS.length) {
public Object getDecodedObject(BerInputStream in) throws IOException {
return new ReasonFlags((boolean[]) super.getDecodedObject(in));
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/TBSCertList.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/TBSCertList.java
index 597ca59..6b04d55 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/TBSCertList.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/TBSCertList.java
@@ -153,6 +153,11 @@
? rcert.crlEntryExtensions == null
: crlEntryExtensions.equals(rcert.crlEntryExtensions));
}
+
+ public int hashCode() {
+ return userCertificate.hashCode() * 37 + (int)revocationDate.getTime() / 1000
+ + (crlEntryExtensions == null ? 0 : crlEntryExtensions.hashCode());
+ }
/**
* Places the string representation of extension value
@@ -171,7 +176,7 @@
}
}
- public static ASN1Sequence ASN1 = new ASN1Sequence(
+ public static final ASN1Sequence ASN1 = new ASN1Sequence(
new ASN1Type[] {ASN1Integer.getInstance(), Time.ASN1,
Extensions.ASN1}) {
{
@@ -358,6 +363,12 @@
? tbscert.crlExtensions == null
: crlExtensions.equals(tbscert.crlExtensions));
}
+
+ public int hashCode() {
+ return ((version * 37 + signature.hashCode()) * 37
+ + issuer.getEncoded().hashCode()) * 37
+ + (int)thisUpdate.getTime() / 1000;
+ }
/**
* Places the string representation of extension value
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/PKIStatusInfo.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/PKIStatusInfo.java
index 336a60d..b0b75a6 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/PKIStatusInfo.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/PKIStatusInfo.java
@@ -59,7 +59,7 @@
}
public String toString(){
- StringBuffer res = new StringBuffer();
+ StringBuilder res = new StringBuilder();
res.append("-- PKIStatusInfo:");
res.append("\nPKIStatus : ");
res.append(status);
@@ -122,8 +122,7 @@
int failInfoValue = -1;
if (values[2] != null) {
- boolean[] failInfoBoolArray = (values[2] == null) ? null
- : ((BitString) values[2]).toBooleanArray();
+ boolean[] failInfoBoolArray = ((BitString) values[2]).toBooleanArray();
for (int i = 0; i < failInfoBoolArray.length; i++) {
if (failInfoBoolArray[i]) {
failInfoValue = i;
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/TSTInfo.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/TSTInfo.java
index 4c9454e..f2aa0ee 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/TSTInfo.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/TSTInfo.java
@@ -102,7 +102,7 @@
}
public String toString() {
- StringBuffer res = new StringBuffer();
+ StringBuilder res = new StringBuilder();
res.append("-- TSTInfo:");
res.append("\nversion: ");
res.append(version);
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/TimeStampReq.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/TimeStampReq.java
index 117ae27..5e4e6ff 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/TimeStampReq.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/TimeStampReq.java
@@ -82,7 +82,7 @@
}
public String toString() {
- StringBuffer res = new StringBuffer();
+ StringBuilder res = new StringBuilder();
res.append("-- TimeStampReq:");
res.append("\nversion : ");
res.append(version);
diff --git a/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/TimeStampResp.java b/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/TimeStampResp.java
index ea50a2d..af03ea5 100644
--- a/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/TimeStampResp.java
+++ b/libcore/security/src/main/java/org/apache/harmony/security/x509/tsp/TimeStampResp.java
@@ -46,7 +46,7 @@
}
public String toString(){
- StringBuffer res = new StringBuffer();
+ StringBuilder res = new StringBuilder();
res.append("-- TimeStampResp:");
res.append("\nstatus: ");
res.append(status);
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/AlgorithmParametersTest.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/AlgorithmParametersTest.java
index bbbe861..13ac904 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/AlgorithmParametersTest.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/AlgorithmParametersTest.java
@@ -709,8 +709,7 @@
params = AlgorithmParameters.getInstance("DSA");
try {
params.init(enc, "DOUGLASMAWSON");
- params.init(enc, "DOUGLASMAWSON");
- fail("IOException exception expected");
+ fail("unsupported format should have raised IOException");
} catch (IOException e) {
// expected
}
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/AllTests.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/AllTests.java
index 2803251..089a7db 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/AllTests.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/AllTests.java
@@ -47,33 +47,26 @@
suite.addTestSuite(CodeSignerTest.class);
suite.addTestSuite(CodeSource2Test.class);
suite.addTestSuite(CodeSourceTest.class);
- suite.addTestSuite(DigestException2Test.class);
suite.addTestSuite(DigestExceptionTest.class);
suite.addTestSuite(DigestInputStream2Test.class);
suite.addTestSuite(DigestInputStreamTest.class);
suite.addTestSuite(DigestOutputStreamTest.class);
- suite.addTestSuite(GeneralSecurityException2Test.class);
suite.addTestSuite(GeneralSecurityExceptionTest.class);
suite.addTestSuite(GuardedObjectTest.class);
suite.addTestSuite(Identity2Test.class);
suite.addTestSuite(IdentityScope2Test.class);
suite.addTestSuite(IdentityScopeTest.class);
- suite.addTestSuite(InvalidAlgorithmParameterException2Test.class);
suite.addTestSuite(InvalidAlgorithmParameterExceptionTest.class);
- suite.addTestSuite(InvalidKeyException2Test.class);
suite.addTestSuite(InvalidKeyExceptionTest.class);
- suite.addTestSuite(InvalidParameterException2Test.class);
suite.addTestSuite(InvalidParameterExceptionTest.class);
suite.addTestSuite(KSCallbackHandlerProtectionTest.class);
suite.addTestSuite(KSPasswordProtectionTest.class);
suite.addTestSuite(KSPrivateKeyEntryTest.class);
suite.addTestSuite(KSSecretKeyEntryTest.class);
suite.addTestSuite(KSTrustedCertificateEntryTest.class);
- suite.addTestSuite(KeyException2Test.class);
suite.addTestSuite(KeyExceptionTest.class);
suite.addTestSuite(KeyFactory2Test.class);
suite.addTestSuite(KeyFactorySpiTest.class);
- suite.addTestSuite(KeyManagementException2Test.class);
suite.addTestSuite(KeyManagementExceptionTest.class);
suite.addTestSuite(KeyPairGenerator1Test.class);
suite.addTestSuite(KeyPairGenerator2Test.class);
@@ -86,7 +79,6 @@
suite.addTestSuite(KeyStore2Test.class);
suite.addTestSuite(KeyStore3Test.class);
suite.addTestSuite(KeyStoreBuilderTest.class);
- suite.addTestSuite(KeyStoreException2Test.class);
suite.addTestSuite(KeyStoreExceptionTest.class);
suite.addTestSuite(KeyStoreSpiTest.class);
suite.addTestSuite(KeyStoreTest.class);
@@ -94,9 +86,7 @@
suite.addTestSuite(MessageDigest1Test.class);
suite.addTestSuite(MessageDigest2Test.class);
suite.addTestSuite(MessageDigestSpiTest.class);
- suite.addTestSuite(NoSuchAlgorithmException2Test.class);
suite.addTestSuite(NoSuchAlgorithmExceptionTest.class);
- suite.addTestSuite(NoSuchProviderException2Test.class);
suite.addTestSuite(NoSuchProviderExceptionTest.class);
suite.addTestSuite(Permission2Test.class);
suite.addTestSuite(PermissionCollectionTest.class);
@@ -109,7 +99,6 @@
suite.addTestSuite(PrivilegedActionExceptionTest.class);
suite.addTestSuite(ProtectionDomainTest.class);
suite.addTestSuite(Provider2Test.class);
- suite.addTestSuite(ProviderException2Test.class);
suite.addTestSuite(ProviderExceptionTest.class);
suite.addTestSuite(ProviderServiceTest.class);
suite.addTestSuite(ProviderTest.class);
@@ -121,7 +110,6 @@
suite.addTestSuite(SecurityPermissionTest.class);
suite.addTestSuite(SecurityTest.class);
suite.addTestSuite(Signature2Test.class);
- suite.addTestSuite(SignatureException2Test.class);
suite.addTestSuite(SignatureExceptionTest.class);
suite.addTestSuite(SignatureSpiTest.class);
suite.addTestSuite(SignatureTest.class);
@@ -129,7 +117,6 @@
suite.addTestSuite(SignerTest.class);
suite.addTestSuite(TimestampTest.class);
suite.addTestSuite(UnrecoverableEntryExceptionTest.class);
- suite.addTestSuite(UnrecoverableKeyException2Test.class);
suite.addTestSuite(UnrecoverableKeyExceptionTest.class);
suite.addTestSuite(UnresolvedPermissionTest.class);
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/CodeSource2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/CodeSource2Test.java
index c70bc57..fa94fbf 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/CodeSource2Test.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/CodeSource2Test.java
@@ -128,7 +128,7 @@
public void test_hashCode() throws Exception {
URL url = new java.net.URL("file:///test");
CodeSource cs = new CodeSource(url, (Certificate[]) null);
- assertTrue("Did not get expected hashCode!", cs.hashCode() == url
+ assertEquals("Did not get expected hashCode!", cs.hashCode(), url
.hashCode());
}
@@ -163,6 +163,7 @@
(Certificate[]) null);
assertEquals("Did not get expected location!", "file:/test", cs
.getLocation().toString());
+ assertNotNull("Host should not be null", cs.getLocation().getHost());
}
/**
@@ -187,7 +188,7 @@
(Certificate[]) null);
cs2 = new CodeSource(new URL("file:/d:/somedir/"), (Certificate[]) null);
assertTrue("null host should imply host", cs1.implies(cs2));
- assertTrue("host should not imply null host", !cs2.implies(cs1));
- }
+ assertFalse("host should not imply null host", cs2.implies(cs1));
+ }
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestException2Test.java
deleted file mode 100644
index 544e618..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestException2Test.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.harmony.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
-import java.security.DigestException;
-
-@TestTargetClass(DigestException.class)
-public class DigestException2Test extends junit.framework.TestCase {
-
- /**
- * @tests java.security.DigestException#DigestException()
- */
- @TestTargetNew(
- level = TestLevel.COMPLETE,
- notes = "",
- method = "DigestException",
- args = {}
- )
- public void test_Constructor() {
- // Test for method java.security.DigestException()
- DigestException de = new DigestException();
- assertNull("Exception with no message should yield null message.", de
- .getMessage());
- }
-
- /**
- * @tests java.security.DigestException#DigestException(java.lang.String)
- */
- @TestTargetNew(
- level = TestLevel.PARTIAL,
- notes = "Different variants of string parameter (empty, null, etc.) weren't checked",
- method = "DigestException",
- args = {java.lang.String.class}
- )
- public void test_ConstructorLjava_lang_String() {
- // Test for method java.security.DigestException(java.lang.String)
- DigestException de = new DigestException("Test message");
- assertEquals("Exception message is incorrect", "Test message", de
- .getMessage());
- }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestInputStream2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestInputStream2Test.java
index 69a73a3..93ffe77 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestInputStream2Test.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestInputStream2Test.java
@@ -19,6 +19,7 @@
import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.io.UnsupportedEncodingException;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -280,4 +281,4 @@
fail("Unable to find SHA-1 algorithm");
}
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestOutputStreamTest.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestOutputStreamTest.java
index 8309c87..ca80f19 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestOutputStreamTest.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/DigestOutputStreamTest.java
@@ -651,32 +651,28 @@
method = "on",
args = {boolean.class}
)
- public void test_onZ() {
+ public void test_onZ() throws Exception {
// Test for method void java.security.DigestOutputStream.on(boolean)
- try {
- DigestOutputStream dos = new DigestOutputStream(
- new ByteArrayOutputStream(), MessageDigest
- .getInstance("SHA"));
- dos.on(false);
- byte digestArray[] = { 23, 43, 44 };
- dos.write(digestArray, 1, 1);
- byte digestResult[] = dos.getMessageDigest().digest();
- byte expected[] = { -38, 57, -93, -18, 94, 107, 75, 13, 50, 85,
- -65, -17, -107, 96, 24, -112, -81, -40, 7, 9 };
- assertTrue("Digest did not return expected result.",
- java.util.Arrays.equals(digestResult, expected));
- // now turn on processing and re-run
- dos.on(true);
- dos.write(digestArray, 1, 1);
- digestResult = dos.getMessageDigest().digest();
- byte expected1[] = { -87, 121, -17, 16, -52, 111, 106, 54, -33,
- 107, -118, 50, 51, 7, -18, 59, -78, -30, -37, -100 };
+ DigestOutputStream dos = new DigestOutputStream(
+ new ByteArrayOutputStream(), MessageDigest
+ .getInstance("SHA"));
+ dos.on(false);
+ byte digestArray[] = { 23, 43, 44 };
+ dos.write(digestArray, 1, 1);
+ byte digestResult[] = dos.getMessageDigest().digest();
+ byte expected[] = { -38, 57, -93, -18, 94, 107, 75, 13, 50, 85,
+ -65, -17, -107, 96, 24, -112, -81, -40, 7, 9 };
+ assertTrue("Digest did not return expected result.",
+ java.util.Arrays.equals(digestResult, expected));
+ // now turn on processing and re-run
+ dos.on(true);
+ dos.write(digestArray, 1, 1);
+ digestResult = dos.getMessageDigest().digest();
+ byte expected1[] = { -87, 121, -17, 16, -52, 111, 106, 54, -33,
+ 107, -118, 50, 51, 7, -18, 59, -78, -30, -37, -100 };
- assertTrue("Digest did not return expected result.",
- java.util.Arrays.equals(digestResult, expected1));
- } catch (Exception e) {
- fail("Caught exception : " + e);
- }
+ assertTrue("Digest did not return expected result.",
+ java.util.Arrays.equals(digestResult, expected1));
}
/**
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/GeneralSecurityException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/GeneralSecurityException2Test.java
deleted file mode 100644
index 3647115..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/GeneralSecurityException2Test.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.harmony.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
-import java.security.GeneralSecurityException;
-
-@TestTargetClass(GeneralSecurityException.class)
-public class GeneralSecurityException2Test extends junit.framework.TestCase {
-
- /**
- * @tests java.security.GeneralSecurityException#GeneralSecurityException()
- */
- @TestTargetNew(
- level = TestLevel.COMPLETE,
- notes = "",
- method = "GeneralSecurityException",
- args = {}
- )
- public void test_Constructor() {
- // Test for method java.security.GeneralSecurityException()
- GeneralSecurityException e = new GeneralSecurityException();
- assertNotNull("Constructor returned null instance", e);
- assertEquals("Failed toString test for constructed instance", "java.security.GeneralSecurityException", e
- .toString());
- }
-
- /**
- * @tests java.security.GeneralSecurityException#GeneralSecurityException(java.lang.String)
- */
- @TestTargetNew(
- level = TestLevel.PARTIAL,
- notes = "Verifies non null parameter only",
- method = "GeneralSecurityException",
- args = {java.lang.String.class}
- )
- public void test_ConstructorLjava_lang_String() {
- // Test for method
- // java.security.GeneralSecurityException(java.lang.String)
- GeneralSecurityException e = new GeneralSecurityException(
- "test message");
- assertNotNull("Constructor returned null instance", e);
- assertEquals("Failed toString test for constructed instance",
- "java.security.GeneralSecurityException: test message", e
- .toString());
- }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Identity2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Identity2Test.java
index 55e2fd2..865bbea 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Identity2Test.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Identity2Test.java
@@ -20,6 +20,7 @@
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
import java.security.Certificate;
import java.security.Identity;
import java.security.IdentityScope;
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/InvalidAlgorithmParameterException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/InvalidAlgorithmParameterException2Test.java
deleted file mode 100644
index dafdb38..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/InvalidAlgorithmParameterException2Test.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.harmony.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
-import java.security.InvalidAlgorithmParameterException;
-
-@TestTargetClass(InvalidAlgorithmParameterException.class)
-public class InvalidAlgorithmParameterException2Test extends
- junit.framework.TestCase {
-
- /**
- * @tests java.security.InvalidAlgorithmParameterException#InvalidAlgorithmParameterException()
- */
- @TestTargetNew(
- level = TestLevel.COMPLETE,
- notes = "",
- method = "InvalidAlgorithmParameterException",
- args = {}
- )
- public void test_Constructor() {
- // Test for method java.security.InvalidAlgorithmParameterException()
- InvalidAlgorithmParameterException e = new InvalidAlgorithmParameterException();
- assertNotNull("Constructor returned null instance", e);
- assertEquals("Failed toString test for constructed instance",
- "java.security.InvalidAlgorithmParameterException", e
- .toString());
- }
-
- /**
- * @tests java.security.InvalidAlgorithmParameterException#InvalidAlgorithmParameterException(java.lang.String)
- */
- @TestTargetNew(
- level = TestLevel.PARTIAL,
- notes = "Verifies constructor with one string parameter",
- method = "InvalidAlgorithmParameterException",
- args = {java.lang.String.class}
- )
- public void test_ConstructorLjava_lang_String() {
- // Test for method
- // java.security.InvalidAlgorithmParameterException(java.lang.String)
- InvalidAlgorithmParameterException e = new InvalidAlgorithmParameterException(
- "test message");
- assertNotNull("Constructor returned null instance", e);
- assertEquals(
- "Failed toString test for constructed instance",
- "java.security.InvalidAlgorithmParameterException: test message",
- e.toString());
- }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/InvalidKeyException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/InvalidKeyException2Test.java
deleted file mode 100644
index bbe9e08..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/InvalidKeyException2Test.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.harmony.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
-import java.security.InvalidKeyException;
-
-@TestTargetClass(InvalidKeyException.class)
-public class InvalidKeyException2Test extends junit.framework.TestCase {
-
- /**
- * @tests java.security.InvalidKeyException#InvalidKeyException()
- */
- @TestTargetNew(
- level = TestLevel.COMPLETE,
- notes = "",
- method = "InvalidKeyException",
- args = {}
- )
- public void test_Constructor() {
- // Test for method java.security.InvalidKeyException()
- InvalidKeyException e = new InvalidKeyException();
- assertNotNull("Constructor returned a null", e);
- assertEquals("Failed toString test for constructed instance", "java.security.InvalidKeyException", e
- .toString());
- }
-
- /**
- * @tests java.security.InvalidKeyException#InvalidKeyException(java.lang.String)
- */
- @TestTargetNew(
- level = TestLevel.PARTIAL,
- notes = "Verifies constructor with one string parameter",
- method = "InvalidKeyException",
- args = {java.lang.String.class}
- )
- public void test_ConstructorLjava_lang_String() {
- // Test for method java.security.InvalidKeyException(java.lang.String)
- InvalidKeyException e = new InvalidKeyException("test message");
- assertNotNull("Constructor returned a null", e);
- assertEquals("Failed toString test for constructed instance",
- "java.security.InvalidKeyException: test message", e
- .toString());
- }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/InvalidParameterException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/InvalidParameterException2Test.java
deleted file mode 100644
index 4830731..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/InvalidParameterException2Test.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.harmony.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
-import java.security.InvalidParameterException;
-
-@TestTargetClass(InvalidParameterException.class)
-public class InvalidParameterException2Test extends junit.framework.TestCase {
-
- /**
- * @tests java.security.InvalidParameterException#InvalidParameterException()
- */
- @TestTargetNew(
- level = TestLevel.COMPLETE,
- notes = "",
- method = "InvalidParameterException",
- args = {}
- )
- public void test_Constructor() {
- // Test for method java.security.InvalidParameterException()
- InvalidParameterException e = new InvalidParameterException();
- assertEquals("Failed toString test for constructed instance", "java.security.InvalidParameterException", e
- .toString());
- }
-
- /**
- * @tests java.security.InvalidParameterException#InvalidParameterException(java.lang.String)
- */
- @TestTargetNew(
- level = TestLevel.PARTIAL,
- notes = "Verifies constructor with one variant of string parameter",
- method = "InvalidParameterException",
- args = {java.lang.String.class}
- )
- public void test_ConstructorLjava_lang_String() {
- // Test for method
- // java.security.InvalidParameterException(java.lang.String)
- InvalidParameterException e = new InvalidParameterException(
- "test message");
- assertEquals("Failed toString test for constructed instance",
-
- "java.security.InvalidParameterException: test message", e
- .toString()
- );
- }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyException2Test.java
deleted file mode 100644
index 1c7b71f..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyException2Test.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.harmony.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
-import java.security.KeyException;
-
-@TestTargetClass(KeyException.class)
-public class KeyException2Test extends junit.framework.TestCase {
-
- /**
- * @tests java.security.KeyException#KeyException()
- */
- @TestTargetNew(
- level = TestLevel.COMPLETE,
- notes = "",
- method = "KeyException",
- args = {}
- )
- public void test_Constructor() {
- // Test for method java.security.KeyException()
- KeyException e = new KeyException();
- assertEquals("Failed toString test for constructed instance", "java.security.KeyException", e
- .toString());
- }
-
- /**
- * @tests java.security.KeyException#KeyException(java.lang.String)
- */
- @TestTargetNew(
- level = TestLevel.PARTIAL,
- notes = "Verifies constructor with one variant of string parameter",
- method = "KeyException",
- args = {java.lang.String.class}
- )
- public void test_ConstructorLjava_lang_String() {
- // Test for method java.security.KeyException(java.lang.String)
- KeyException e = new KeyException("test message");
- assertEquals("Failed toString test for constructed instance", "java.security.KeyException: test message", e
- .toString());
- }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyManagementException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyManagementException2Test.java
deleted file mode 100644
index c30370a..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyManagementException2Test.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.harmony.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
-import java.security.KeyManagementException;
-
-@TestTargetClass(KeyManagementException.class)
-public class KeyManagementException2Test extends junit.framework.TestCase {
-
- /**
- * @tests java.security.KeyManagementException#KeyManagementException()
- */
- @TestTargetNew(
- level = TestLevel.COMPLETE,
- notes = "",
- method = "KeyManagementException",
- args = {}
- )
- public void test_Constructor() {
- // Test for method java.security.KeyManagementException()
- KeyManagementException e = new KeyManagementException();
- assertEquals("Failed toString test for constructed instance",
- "java.security.KeyManagementException", e.toString());
- }
-
- /**
- * @tests java.security.KeyManagementException#KeyManagementException(java.lang.String)
- */
- @TestTargetNew(
- level = TestLevel.PARTIAL,
- notes = "Checking with null and empty string parameter missed",
- method = "KeyManagementException",
- args = {java.lang.String.class}
- )
- public void test_ConstructorLjava_lang_String() {
- // Test for method
- // java.security.KeyManagementException(java.lang.String)
- KeyManagementException e = new KeyManagementException("test message");
- assertEquals("Failed toString test for constructed instance",
- "java.security.KeyManagementException: test message",
- e.toString());
- }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStore2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStore2Test.java
index 817de35..059cef4 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStore2Test.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStore2Test.java
@@ -1372,4 +1372,4 @@
}
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreException2Test.java
deleted file mode 100644
index b3c9583..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreException2Test.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.harmony.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
-import java.security.KeyStoreException;
-
-@TestTargetClass(KeyStoreException.class)
-public class KeyStoreException2Test extends junit.framework.TestCase {
-
- /**
- * @tests java.security.KeyStoreException#KeyStoreException()
- */
- @TestTargetNew(
- level = TestLevel.COMPLETE,
- notes = "",
- method = "KeyStoreException",
- args = {}
- )
- public void test_Constructor() {
- // Test for method java.security.KeyStoreException()
- KeyStoreException e = new KeyStoreException();
- assertEquals("Failed toString test for constructed instance", "java.security.KeyStoreException", e
- .toString());
- }
-
- /**
- * @tests java.security.KeyStoreException#KeyStoreException(java.lang.String)
- */
- @TestTargetNew(
- level = TestLevel.PARTIAL,
- notes = "Verifies constructor with one variant of string parameter",
- method = "KeyStoreException",
- args = {java.lang.String.class}
- )
- public void test_ConstructorLjava_lang_String() {
- // Test for method java.security.KeyStoreException(java.lang.String)
- KeyStoreException e = new KeyStoreException("test message");
- assertEquals("Failed toString test for constructed instance",
- "java.security.KeyStoreException: test message", e
- .toString());
- }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStorePrivateKeyEntryTest.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStorePrivateKeyEntryTest.java
new file mode 100644
index 0000000..42feeec
--- /dev/null
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStorePrivateKeyEntryTest.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.harmony.security.tests.java.security;
+
+import java.io.ByteArrayInputStream;
+import java.io.UnsupportedEncodingException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+
+import junit.framework.TestCase;
+
+public class KeyStorePrivateKeyEntryTest extends TestCase {
+
+ public void testGetCertificateChain() throws Exception {
+
+ String certificateData = "-----BEGIN CERTIFICATE-----\n"
+ + "MIICZTCCAdICBQL3AAC2MA0GCSqGSIb3DQEBAgUAMF8xCzAJBgNVBAYTAlVTMSAw\n"
+ + "HgYDVQQKExdSU0EgRGF0YSBTZWN1cml0eSwgSW5jLjEuMCwGA1UECxMlU2VjdXJl\n"
+ + "IFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05NzAyMjAwMDAwMDBa\n"
+ + "Fw05ODAyMjAyMzU5NTlaMIGWMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZv\n"
+ + "cm5pYTESMBAGA1UEBxMJUGFsbyBBbHRvMR8wHQYDVQQKExZTdW4gTWljcm9zeXN0\n"
+ + "ZW1zLCBJbmMuMSEwHwYDVQQLExhUZXN0IGFuZCBFdmFsdWF0aW9uIE9ubHkxGjAY\n"
+ + "BgNVBAMTEWFyZ29uLmVuZy5zdW4uY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB\n"
+ + "iQKBgQCofmdY+PiUWN01FOzEewf+GaG+lFf132UpzATmYJkA4AEA/juW7jSi+LJk\n"
+ + "wJKi5GO4RyZoyimAL/5yIWDV6l1KlvxyKslr0REhMBaD/3Z3EsLTTEf5gVrQS6sT\n"
+ + "WMoSZAyzB39kFfsB6oUXNtV8+UKKxSxKbxvhQn267PeCz5VX2QIDAQABMA0GCSqG\n"
+ + "SIb3DQEBAgUAA34AXl3at6luiV/7I9MN5CXYoPJYI8Bcdc1hBagJvTMcmlqL2uOZ\n"
+ + "H9T5hNMEL9Tk6aI7yZPXcw/xI2K6pOR/FrMp0UwJmdxX7ljV6ZtUZf7pY492UqwC\n"
+ + "1777XQ9UEZyrKJvF5ntleeO0ayBqLGVKCWzWZX9YsXCpv47FNLZbupE=\n"
+ + "-----END CERTIFICATE-----\n";
+
+ ByteArrayInputStream certArray;
+ {
+ try{
+ certArray = new ByteArrayInputStream(
+ certificateData.getBytes("UTF-8"));
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ Certificate certificate = cf.generateCertificate(certArray);
+ assertTrue(certificate instanceof X509Certificate);
+
+ String algorithm = certificate.getPublicKey().getAlgorithm();
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator
+ .getInstance(algorithm);
+ KeyPair keyPair = keyPairGenerator.generateKeyPair();
+ PrivateKey privateKey = keyPair.getPrivate();
+
+ // If all the certificate in the chain is X509Certificate,
+ // KeyStore.PrivateKeyEntry will return a X509Certificate array.
+ KeyStore.PrivateKeyEntry privateKeyEntry = new KeyStore.PrivateKeyEntry(
+ privateKey, new Certificate[] { certificate });
+ Certificate[] chain = privateKeyEntry.getCertificateChain();
+ assertTrue(chain instanceof X509Certificate[]);
+
+ }
+}
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreTest.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreTest.java
index d7ae43f..210116e 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreTest.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/KeyStoreTest.java
@@ -47,6 +47,8 @@
import java.util.Date;
import java.util.Set;
import java.math.BigInteger;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
import org.apache.harmony.security.tests.support.KeyStoreTestSupport;
import org.apache.harmony.security.tests.support.MyLoadStoreParams;
@@ -277,6 +279,35 @@
}
+
+ /*
+ * @tests java.security.KeyStoreSpi.engineEntryInstanceOf(String, Class<? extends Entry>)
+ */
+ public void testEngineEntryInstanceOf() throws Exception {
+ //Regression for HARMONY-615
+
+ // create a KeyStore
+ KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ keyStore.load(null, "pwd".toCharArray());
+
+ // generate a key
+ KeyGenerator keyGen = KeyGenerator.getInstance("DES");
+ keyGen.init(56);
+ SecretKey secretKey = keyGen.generateKey();
+
+ // put the key into keystore
+ String alias = "alias";
+ keyStore.setKeyEntry(alias, secretKey, "pwd".toCharArray(), null);
+
+ // check if it is a secret key
+ assertTrue(keyStore.entryInstanceOf(alias,
+ KeyStore.SecretKeyEntry.class));
+
+ // check if it is NOT a private key
+ assertFalse(keyStore.entryInstanceOf(alias,
+ KeyStore.PrivateKeyEntry.class));
+ }
+
/**
* @tests java.security.KeyStore.TrustedCertificateEntry.toString()
*/
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigest2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigest2Test.java
index c26708d..9eca936 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigest2Test.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigest2Test.java
@@ -25,6 +25,7 @@
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
+import java.io.UnsupportedEncodingException;
import java.security.DigestException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -676,4 +677,4 @@
}
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigestSpiTest.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigestSpiTest.java
index b7c11e5..8bcb392 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigestSpiTest.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigestSpiTest.java
@@ -109,29 +109,29 @@
)
public void test_engineDigestLB$LILI() throws Exception {
- final int DIGEST_LENGHT = 2;
+ final int DIGEST_LENGTH = 2;
MyMessageDigest md = new MyMessageDigest() {
public int engineGetDigestLength() {
- return DIGEST_LENGHT;
+ return DIGEST_LENGTH;
}
public byte[] engineDigest() {
- return new byte[DIGEST_LENGHT]; // return non-null value
+ return new byte[DIGEST_LENGTH]; // return non-null value
}
};
byte[] b = new byte[5];
try {
// test: null output buffer
- md.engineDigest(null, 1, DIGEST_LENGHT);
+ md.engineDigest(null, 1, DIGEST_LENGTH);
fail("No expected NullPointerException");
} catch (NullPointerException e) {
}
try {
//test: len param < digest length
- md.engineDigest(b, 1, DIGEST_LENGHT - 1);
+ md.engineDigest(b, 1, DIGEST_LENGTH - 1);
fail("No expected DigestException");
} catch (DigestException e) {
}
@@ -153,7 +153,7 @@
// ok
}
- assertEquals("incorrect result", DIGEST_LENGHT, md
+ assertEquals("incorrect result", DIGEST_LENGTH, md
.engineDigest(b, 1, 3));
// Regression for HARMONY-3045
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/NoSuchAlgorithmException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/NoSuchAlgorithmException2Test.java
deleted file mode 100644
index 289047b..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/NoSuchAlgorithmException2Test.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.harmony.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
-import java.security.NoSuchAlgorithmException;
-
-@TestTargetClass(NoSuchAlgorithmException.class)
-public class NoSuchAlgorithmException2Test extends junit.framework.TestCase {
-
- /**
- * @tests java.security.NoSuchAlgorithmException#NoSuchAlgorithmException()
- */
- @TestTargetNew(
- level = TestLevel.COMPLETE,
- notes = "",
- method = "NoSuchAlgorithmException",
- args = {}
- )
- public void test_Constructor() {
- try {
- throw new NoSuchAlgorithmException();
- } catch (NoSuchAlgorithmException e) {
- assertNull("Message should be null", e.getMessage());
- assertEquals("Unexpected toString value",
- "java.security.NoSuchAlgorithmException", e.toString());
- }
- }
-
- /**
- * @tests java.security.NoSuchAlgorithmException#NoSuchAlgorithmException(java.lang.String)
- */
- @TestTargetNew(
- level = TestLevel.PARTIAL,
- notes = "Null parameter checking missed",
- method = "NoSuchAlgorithmException",
- args = {java.lang.String.class}
- )
- public void test_ConstructorLjava_lang_String() {
- // Test for method
- // java.security.NoSuchAlgorithmException(java.lang.String)
- try {
- throw new NoSuchAlgorithmException("Test string");
- } catch (NoSuchAlgorithmException e) {
- assertEquals("Wrong message", "Test string", e.getMessage());
- assertEquals("Unexpected toString value",
- "java.security.NoSuchAlgorithmException: Test string", e
- .toString());
- }
- }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/NoSuchProviderException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/NoSuchProviderException2Test.java
deleted file mode 100644
index 256ed66..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/NoSuchProviderException2Test.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.harmony.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
-import java.security.NoSuchProviderException;
-
-@TestTargetClass(NoSuchProviderException.class)
-public class NoSuchProviderException2Test extends junit.framework.TestCase {
-
- /**
- * @tests java.security.NoSuchProviderException#NoSuchProviderException()
- */
- @TestTargetNew(
- level = TestLevel.COMPLETE,
- notes = "",
- method = "NoSuchProviderException",
- args = {}
- )
- public void test_Constructor() {
- // Test for method java.security.NoSuchProviderException()
- try {
- throw new NoSuchProviderException();
- } catch (NoSuchProviderException e) {
- assertNull("Message should be null", e.getMessage());
- assertEquals("Unexpected toString value",
- "java.security.NoSuchProviderException", e.toString());
- }
- }
-
- /**
- * @tests java.security.NoSuchProviderException#NoSuchProviderException(java.lang.String)
- */
- @TestTargetNew(
- level = TestLevel.PARTIAL,
- notes = "Null parameter checking missed",
- method = "NoSuchProviderException",
- args = {java.lang.String.class}
- )
- public void test_ConstructorLjava_lang_String() {
- // Test for method
- // java.security.NoSuchProviderException(java.lang.String)
- try {
- throw new NoSuchProviderException("Test string");
- } catch (NoSuchProviderException e) {
- assertEquals("Wrong message", "Test string", e.getMessage());
- assertEquals("Unexpected toString value",
- "java.security.NoSuchProviderException: Test string", e
- .toString());
- }
- }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Permissions2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Permissions2Test.java
index af33804..a60adbf 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Permissions2Test.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Permissions2Test.java
@@ -55,7 +55,7 @@
public void test_Constructor() {
// Test for method java.security.Permissions()
new Permissions();
- }
+ }
/**
* @tests java.security.Permissions#add(java.security.Permission)
@@ -192,4 +192,4 @@
public void checkPermission(Permission permission) {
}
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/PolicyTest.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/PolicyTest.java
index 78038b5..cfa2af1 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/PolicyTest.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/PolicyTest.java
@@ -395,7 +395,7 @@
String policyFile = getClass().getClassLoader().getResource(
"PolicyTest.txt").toString();
- String oldSysProp = System.getProperty(JAVA_SECURITY_POLICY);
+ String oldJavaPolicy = System.getProperty(JAVA_SECURITY_POLICY);
Policy oldPolicy = Policy.getPolicy();
try {
@@ -404,12 +404,20 @@
// test: absolute paths
assertCodeBasePropertyExpansion("/11111/*", "/11111/-");
assertCodeBasePropertyExpansion("/22222/../22222/*", "/22222/-");
+ assertCodeBasePropertyExpansion("/33333/*", "/33333/../33333/-");
+ assertCodeBasePropertyExpansion("/44444/../44444/-", "/44444/*");
+ assertCodeBasePropertyExpansion("/55555/../55555/-", "/55555/../55555/-");
+ assertCodeBasePropertyExpansion("/666 66 66/-", "/666 66 66/-");
// test: relative paths
- assertCodeBasePropertyExpansion("44444/*", "44444/-");
- assertCodeBasePropertyExpansion("55555/../55555/*", "55555/-");
+ assertCodeBasePropertyExpansion("11111/*", "11111/-");
+ assertCodeBasePropertyExpansion("22222/../22222/*", "22222/-");
+ assertCodeBasePropertyExpansion("33333/*", "33333/../33333/-");
+ assertCodeBasePropertyExpansion("44444/../44444/-", "44444/*");
+ assertCodeBasePropertyExpansion("55555/../55555/-", "55555/../55555/-");
+ assertCodeBasePropertyExpansion("666 66 66/-", "666 66 66/-");
} finally {
- TestUtils.setSystemProperty(JAVA_SECURITY_POLICY, oldSysProp);
+ TestUtils.setSystemProperty(JAVA_SECURITY_POLICY, oldJavaPolicy);
Policy.setPolicy(oldPolicy);
}
}
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Provider2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Provider2Test.java
index 48e8f32..a8ec69a 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Provider2Test.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Provider2Test.java
@@ -22,7 +22,10 @@
import dalvik.annotation.TestLevel;
import dalvik.annotation.TestTargetNew;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.security.Provider;
+import java.security.Security;
@TestTargetClass(Provider.class)
public class Provider2Test extends junit.framework.TestCase {
@@ -172,4 +175,44 @@
// Regression for HARMONY-3734
assertEquals("provTest version 1.2", provTest.toString());
}
+
+ // Regression Test for Provider.Service.getAlias(), which is an package
+ // private method but will lead to NPE thrown at
+ // Secure.SecurityDorr.getAliases
+ public void test_getAlias() throws Exception {
+ MockProvider mockProvider = new MockProvider("MOCKNAME", 1.0,
+ "MOCKINFO");
+ Provider.Service service = new Provider.Service(mockProvider,
+ "MOCKTYPE", "MOCKALGORITHM", "TESTCLASSNAME", null, null);
+ mockProvider.putService(service);
+ Security.addProvider(mockProvider);
+ try {
+ MessageDigest messageDigest = MessageDigest
+ .getInstance("NOTEXISTS");
+ }
+
+ catch (NoSuchAlgorithmException e) {
+ // expected
+ } finally {
+ Security.removeProvider("MOCKNAME");
+ }
+ }
+
+ public static class MockProvider extends Provider {
+
+ private static final long serialVersionUID = 1L;
+
+ public MockProvider(String name, double version, String info) {
+ super(name, version, info);
+
+ }
+
+ public void putService(Provider.Service service) {
+ super.putService(service);
+ }
+
+ public void removeService(Provider.Service service) {
+ super.removeService(service);
+ }
+ }
}
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderException2Test.java
deleted file mode 100644
index 4b0f2ec..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderException2Test.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.harmony.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
-import java.security.ProviderException;
-
-@TestTargetClass(ProviderException.class)
-public class ProviderException2Test extends junit.framework.TestCase {
-
- /**
- * @tests java.security.ProviderException#ProviderException()
- */
- @TestTargetNew(
- level = TestLevel.COMPLETE,
- notes = "",
- method = "ProviderException",
- args = {}
- )
- public void test_Constructor() {
- // Test for method java.security.ProviderException()
- ProviderException e = new ProviderException();
- assertEquals("Failed toString test for constructed instance",
- "java.security.ProviderException", e.toString());
- }
-
- /**
- * @tests java.security.ProviderException#ProviderException(java.lang.String)
- */
- @TestTargetNew(
- level = TestLevel.PARTIAL,
- notes = "Verification with null/empty parameter is absent",
- method = "ProviderException",
- args = {java.lang.String.class}
- )
- public void test_ConstructorLjava_lang_String() {
- // Test for method java.security.ProviderException(java.lang.String)
- ProviderException e = new ProviderException("test message");
- assertEquals("Failed toString test for constructed instance",
- "java.security.ProviderException: test message", e
- .toString());
- }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderServiceTest.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderServiceTest.java
index c93011c..730e329 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderServiceTest.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderServiceTest.java
@@ -138,22 +138,16 @@
method = "newInstance",
args = {java.lang.Object.class}
)
- public void testNewInstance() {
+ public void testNewInstance() throws Exception {
Provider p = new MyProvider();
Provider.Service s = new Provider.Service(p, "SecureRandom",
- "algorithm", "org.apache.harmony.security.tests.support.RandomImpl", null,
- null);
- Object o = null;
- try {
- o = s.newInstance(null);
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- fail("newInstance() failed");
- }
- if (!(o instanceof RandomImpl)) {
- fail("incorrect instance");
- }
+ "algorithm",
+ "org.apache.harmony.security.tests.support.RandomImpl",
+ null, null);
+ Object o = s.newInstance(null);
+ assertTrue("incorrect instance", o instanceof RandomImpl);
+
try {
o = s.newInstance(new Object());
fail("No expected NoSuchAlgorithmException");
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderTest.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderTest.java
index a3b3077..3cc447f 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderTest.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/ProviderTest.java
@@ -129,27 +129,9 @@
)
public final void testClear() {
p.clear();
- if (p.getProperty("MessageDigest.ASH-1") != null) {
- fail("Provider contains properties");
- }
+ assertNull(p.getProperty("MessageDigest.SHA-1"));
}
- @TestTargetNew(
- level = TestLevel.PARTIAL_COMPLETE,
- notes = "",
- method = "clear",
- args = {}
- )
- public final void testClear_SecurityManager() {
- TestSecurityManager sm = new TestSecurityManager("clearProviderProperties.MyProvider");
- System.setSecurityManager(sm);
- p.clear();
- assertTrue("Provider.clear must call checkPermission with "
- + "SecurityPermission clearProviderProperties.NAME",
- sm.called);
- System.setSecurityManager(null);
- }
-
/*
* Class under test for void Provider(String, double, String)
*/
@@ -161,22 +143,13 @@
)
public final void testProviderStringdoubleString() {
Provider p = new MyProvider("Provider name", 123.456, "Provider info");
- if (!p.getName().equals("Provider name") || p.getVersion() != 123.456
- || !p.getInfo().equals("Provider info")) {
- fail("Incorrect values");
- }
+ assertEquals("Provider name", p.getName());
+ assertEquals(123.456, p.getVersion(), 0L);
+ assertEquals("Provider info", p.getInfo());
}
- @TestTargetNew(
- level = TestLevel.COMPLETE,
- notes = "",
- method = "getName",
- args = {}
- )
public final void testGetName() {
- if (!p.getName().equals("MyProvider")) {
- fail("Incorrect provider name");
- }
+ assertEquals("MyProvider", p.getName());
}
@TestTargetNew(
@@ -186,9 +159,7 @@
args = {}
)
public final void testGetVersion() {
- if (p.getVersion() != 1.0) {
- fail("Incorrect provider version");
- }
+ assertEquals(1.0, p.getVersion(), 0L);
}
@TestTargetNew(
@@ -198,9 +169,7 @@
args = {}
)
public final void testGetInfo() {
- if (!p.getInfo().equals("Provider for testing")) {
- fail("Incorrect provider info");
- }
+ assertEquals("Provider for testing", p.getInfo());
}
/*
@@ -213,19 +182,16 @@
args = {java.util.Map.class}
)
public final void testPutAllMap() {
- HashMap<String, String> hm = new HashMap<String, String>();
- hm.put("MessageDigest.ASH-1", "aaa.bbb.ccc.ddd");
+ HashMap hm = new HashMap();
+ hm.put("MessageDigest.SHA-1", "aaa.bbb.ccc.ddd");
hm.put("Property 1", "value 1");
hm.put("serviceName.algName attrName", "attrValue");
- hm.put("Alg.Alias.engineClassName.aliasName", "stanbdardName");
+ hm.put("Alg.Alias.engineClassName.aliasName", "standardName");
p.putAll(hm);
- if (!"value 1".equals(p.getProperty("Property 1").trim())
- || !"attrValue".equals(p.getProperty(
- "serviceName.algName attrName").trim())
- || !"stanbdardName".equals(p.getProperty(
- "Alg.Alias.engineClassName.aliasName").trim())
- || !"aaa.bbb.ccc.ddd".equals(p.getProperty(
- "MessageDigest.ASH-1").trim())) {
+ if (!"value 1".equals(p.getProperty("Property 1").trim()) ||
+ !"attrValue".equals(p.getProperty("serviceName.algName attrName").trim()) ||
+ !"standardName".equals(p.getProperty("Alg.Alias.engineClassName.aliasName").trim()) ||
+ !"aaa.bbb.ccc.ddd".equals(p.getProperty("MessageDigest.SHA-1").trim()) ) {
fail("Incorrect property value");
}
}
@@ -240,48 +206,43 @@
args = {}
)
public final void testEntrySet() {
- p.put("MessageDigest.ASH-256", "aaa.bbb.ccc.ddd");
-
- Set<Map.Entry<Object, Object>> s = p.entrySet();
+ p.put("MessageDigest.SHA-256", "aaa.bbb.ccc.ddd");
+
+ Set s = p.entrySet();
try {
s.clear();
fail("Must return unmodifiable set");
} catch (UnsupportedOperationException e) {
}
-
+
assertEquals("Incorrect set size", 8, s.size());
-
- for (Iterator<Entry<Object, Object>> it = s.iterator(); it.hasNext();) {
- Entry<Object, Object> e = it.next();
- String key = (String) e.getKey();
- String val = (String) e.getValue();
- if (key.equals("MessageDigest.ASH-1")
- && val.equals("SomeClassName")) {
+
+ for (Iterator it = s.iterator(); it.hasNext();) {
+ Entry e = (Entry)it.next();
+ String key = (String)e.getKey();
+ String val = (String)e.getValue();
+ if (key.equals("MessageDigest.SHA-1") && val.equals("SomeClassName")) {
continue;
}
- if (key.equals("Alg.Alias.MessageDigest.ASH1")
- && val.equals("ASH-1")) {
+ if (key.equals("Alg.Alias.MessageDigest.SHA1") && val.equals("SHA-1")) {
continue;
}
if (key.equals("MessageDigest.abc") && val.equals("SomeClassName")) {
continue;
}
- if (key.equals("Provider.id className")
- && val.equals(p.getClass().getName())) {
+ if (key.equals("Provider.id className") && val.equals(p.getClass().getName())) {
continue;
}
if (key.equals("Provider.id name") && val.equals("MyProvider")) {
continue;
}
- if (key.equals("MessageDigest.ASH-256")
- && val.equals("aaa.bbb.ccc.ddd")) {
+ if (key.equals("MessageDigest.SHA-256") && val.equals("aaa.bbb.ccc.ddd")) {
continue;
}
if (key.equals("Provider.id version") && val.equals("1.0")) {
continue;
}
- if (key.equals("Provider.id info")
- && val.equals("Provider for testing")) {
+ if (key.equals("Provider.id info") && val.equals("Provider for testing")) {
continue;
}
fail("Incorrect set");
@@ -298,30 +259,27 @@
args = {}
)
public final void testKeySet() {
- p.put("MessageDigest.ASH-256", "aaa.bbb.ccc.ddd");
+ p.put("MessageDigest.SHA-256", "aaa.bbb.ccc.ddd");
Set<Object> s = p.keySet();
try {
s.clear();
} catch (UnsupportedOperationException e) {
}
- Set<Object> s1 = p.keySet();
- if ((s == s1) || s1.isEmpty()) {
- fail("Must return unmodifiable set");
- }
- if (s1.size() != 8) {
- fail("Incorrect set size");
- }
- if (!s1.contains("MessageDigest.ASH-256")
- || !s1.contains("MessageDigest.ASH-1")
- || !s1.contains("Alg.Alias.MessageDigest.ASH1")
- || !s1.contains("MessageDigest.abc")
- || !s1.contains("Provider.id info")
- || !s1.contains("Provider.id className")
- || !s1.contains("Provider.id version")
- || !s1.contains("Provider.id name")) {
- fail("Incorrect set");
- }
+ Set s1 = p.keySet();
+
+ assertNotSame(s, s1);
+ assertFalse(s1.isEmpty());
+ assertEquals(8, s1.size());
+
+ assertTrue(s1.contains("MessageDigest.SHA-256"));
+ assertTrue(s1.contains("MessageDigest.SHA-1"));
+ assertTrue(s1.contains("Alg.Alias.MessageDigest.SHA1"));
+ assertTrue(s1.contains("MessageDigest.abc"));
+ assertTrue(s1.contains("Provider.id info"));
+ assertTrue(s1.contains("Provider.id className"));
+ assertTrue(s1.contains("Provider.id version"));
+ assertTrue(s1.contains("Provider.id name"));
}
/*
@@ -341,19 +299,19 @@
c.clear();
} catch (UnsupportedOperationException e) {
}
- Collection<Object> c1 = p.values();
- if ((c == c1) || c1.isEmpty()) {
- fail("Must return unmodifiable set");
- }
- if (c1.size() != 8) {
- fail("Incorrect set size " + c1.size());
- }
- if (!c1.contains("MyProvider") || !c1.contains("aaa.bbb.ccc.ddd")
- || !c1.contains("Provider for testing") || !c1.contains("1.0")
- || !c1.contains("SomeClassName") || !c1.contains("ASH-1")
- || !c1.contains(p.getClass().getName())) {
- fail("Incorrect set");
- }
+ Collection c1 = p.values();
+
+ assertNotSame(c, c1);
+ assertFalse(c1.isEmpty());
+ assertEquals(8, c1.size());
+
+ assertTrue(c1.contains("MyProvider"));
+ assertTrue(c1.contains("aaa.bbb.ccc.ddd"));
+ assertTrue(c1.contains("Provider for testing"));
+ assertTrue(c1.contains("1.0"));
+ assertTrue(c1.contains("SomeClassName"));
+ assertTrue(c1.contains("SHA-1"));
+ assertTrue(c1.contains(p.getClass().getName()));
}
/*
@@ -366,38 +324,124 @@
args = {java.lang.Object.class, java.lang.Object.class}
)
public final void testPutObjectObject() {
- p.put("MessageDigest.ASH-1", "aaa.bbb.ccc.ddd");
+ p.put("MessageDigest.SHA-1", "aaa.bbb.ccc.ddd");
p.put("Type.Algorithm", "className");
- if (!"aaa.bbb.ccc.ddd".equals(p.getProperty("MessageDigest.ASH-1")
- .trim())) {
- fail("Incorrect property value");
- }
-
- Set<Service> services = p.getServices();
- if (services.size() != 3) {
- fail("incorrect size");
- }
- for (Iterator<Service> it = services.iterator(); it.hasNext();) {
- Provider.Service s = it.next();
- if ("Type".equals(s.getType())
- && "Algorithm".equals(s.getAlgorithm())
- && "className".equals(s.getClassName())) {
+ assertEquals("aaa.bbb.ccc.ddd", p.getProperty("MessageDigest.SHA-1")
+ .trim());
+
+ Set services = p.getServices();
+ assertEquals(3, services.size());
+
+ for (Iterator it = services.iterator(); it.hasNext();) {
+ Provider.Service s = (Provider.Service)it.next();
+ if ("Type".equals(s.getType()) &&
+ "Algorithm".equals(s.getAlgorithm()) &&
+ "className".equals(s.getClassName())) {
continue;
}
- if ("MessageDigest".equals(s.getType())
- && "ASH-1".equals(s.getAlgorithm())
- && "aaa.bbb.ccc.ddd".equals(s.getClassName())) {
+ if ("MessageDigest".equals(s.getType()) &&
+ "SHA-1".equals(s.getAlgorithm()) &&
+ "aaa.bbb.ccc.ddd".equals(s.getClassName())) {
continue;
}
- if ("MessageDigest".equals(s.getType())
- && "abc".equals(s.getAlgorithm())
- && "SomeClassName".equals(s.getClassName())) {
+ if ("MessageDigest".equals(s.getType()) &&
+ "abc".equals(s.getAlgorithm()) &&
+ "SomeClassName".equals(s.getClassName())) {
continue;
}
fail("Incorrect service");
}
}
+ /*
+ * Class under test for Object remove(Object)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "remove",
+ args = {java.lang.Object.class}
+ )
+ public final void testRemoveObject() {
+ Object o = p.remove("MessageDigest.SHA-1");
+
+ assertEquals("SomeClassName", o);
+ assertNull(p.getProperty("MessageDigest.SHA-1"));
+ assertEquals(1, p.getServices().size());
+ }
+
+ public final void testService1() {
+ p.put("MessageDigest.SHA-1", "AnotherClassName");
+ Provider.Service s = p.getService("MessageDigest", "SHA-1");
+
+ assertEquals("AnotherClassName", s.getClassName());
+ }
+
+ // Regression for HARMONY-2760.
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Regression test: verifies constructor with two null parameters.",
+ method = "Provider",
+ args = {java.lang.String.class, double.class, java.lang.String.class}
+ )
+ public void testConstructor() {
+ MyProvider myProvider = new MyProvider(null, 1, null);
+ assertNull(myProvider.getName());
+ assertNull(myProvider.getInfo());
+ assertEquals("null", myProvider.getProperty("Provider.id name"));
+ assertEquals("null", myProvider.getProperty("Provider.id info"));
+ }
+
+ class MyProvider extends Provider {
+ MyProvider() {
+ super("MyProvider", 1.0, "Provider for testing");
+ put("MessageDigest.SHA-1", "SomeClassName");
+ put("MessageDigest.abc", "SomeClassName");
+ put("Alg.Alias.MessageDigest.SHA1", "SHA-1");
+ }
+
+ MyProvider(String name, double version, String info) {
+ super(name, version, info);
+ }
+
+ // BEGIN android-added
+ public void putService(Provider.Service s) {
+ super.putService(s);
+ }
+ // END android-added
+
+ // BEGIN android-added
+ public void removeService(Provider.Service s) {
+ super.removeService(s);
+ }
+ // END android-added
+
+ // BEGIN android-added
+ public int getNumServices() {
+ return getServices().size();
+ }
+ // END android-added
+ }
+
+ // BEGIN android-added
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "",
+ method = "clear",
+ args = {}
+ )
+ public final void testClear_SecurityManager() {
+ TestSecurityManager sm = new TestSecurityManager("clearProviderProperties.MyProvider");
+ System.setSecurityManager(sm);
+ p.clear();
+ assertTrue("Provider.clear must call checkPermission with "
+ + "SecurityPermission clearProviderProperties.NAME",
+ sm.called);
+ System.setSecurityManager(null);
+ }
+ // END android-added
+
+ // BEGIN android-added
@TestTargetNew(
level = TestLevel.PARTIAL_COMPLETE,
notes = "",
@@ -414,39 +458,9 @@
+ "SecurityPermission putProviderProperty.Name", sm.called);
System.setSecurityManager(null);
}
+ // END android-added
- /*
- * Class under test for Object remove(Object)
- */
- @TestTargetNew(
- level = TestLevel.COMPLETE,
- notes = "",
- method = "remove",
- args = {java.lang.Object.class}
- )
- public final void testRemoveObject() {
- Object o = p.remove("MessageDigest.ASH-1");
- if (!"SomeClassName".equals(o)) {
- fail("Incorrect return value");
- }
- if (p.getProperty("MessageDigest.ASH-1") != null) {
- fail("Provider contains properties");
- }
- if (p.getServices().size() != 1) {
- fail("Service not removed");
- }
-
- try {
- p.remove(null);
- fail("expected NullPointerException");
- } catch (NullPointerException e) {
- // ok
- }
- }
-
- /*
- * Class under test for Object remove(Object)
- */
+ // BEGIN android-added
@TestTargetNew(
level = TestLevel.PARTIAL_COMPLETE,
notes = "",
@@ -463,35 +477,9 @@
sm.called);
System.setSecurityManager(null);
}
+ // END android-added
- @TestTargetNew(
- level = TestLevel.COMPLETE,
- notes = "",
- method = "getService",
- args = {java.lang.String.class, java.lang.String.class}
- )
- public final void testService1() {
- p.put("MessageDigest.ASH-1", "AnotherClassName");
- Provider.Service s = p.getService("MessageDigest", "ASH-1");
- if (!"AnotherClassName".equals(s.getClassName())) {
- fail("Incorrect class name " + s.getClassName());
- }
-
- try {
- p.getService("MessageDigest", null);
- fail("expected NullPointerException");
- } catch (NullPointerException e) {
- // ok;
- }
-
- try {
- p.getService(null, "ASH-1");
- fail("expected NullPointerException");
- } catch (NullPointerException e) {
- // ok
- }
- }
-
+ // BEGIN android-added
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
@@ -516,23 +504,9 @@
} catch (NoSuchAlgorithmException e) {
}
}
-
+ // END android-added
- // Regression for HARMONY-2760.
- @TestTargetNew(
- level = TestLevel.PARTIAL_COMPLETE,
- notes = "Regression test: verifies constructor with two null parameters.",
- method = "Provider",
- args = {java.lang.String.class, double.class, java.lang.String.class}
- )
- public void testConstructor() {
- MyProvider myProvider = new MyProvider(null, 1, null);
- assertNull(myProvider.getName());
- assertNull(myProvider.getInfo());
- assertEquals("null", myProvider.getProperty("Provider.id name"));
- assertEquals("null", myProvider.getProperty("Provider.id info"));
- }
-
+ // BEGIN android-added
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
@@ -576,7 +550,9 @@
assertTrue(!actual.contains(s[1]));
assertTrue(actual.contains(s[2]));
}
+ // END android-added
+ // BEGIN android-added
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
@@ -631,7 +607,9 @@
// expected
}
}
+ // END android-added
+ // BEGIN android-added
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
@@ -703,10 +681,9 @@
// expected
}
}
+ // END android-added
- /*
- * Class under test for void load(InputStream)
- */
+ // BEGIN android-added
@TestTargetNew(
level = TestLevel.PARTIAL_COMPLETE,
notes = "",
@@ -735,7 +712,9 @@
// expected
}
}
-
+ // END android-added
+
+ // BEGIN android-added
@TestTargetNew(
level = TestLevel.PARTIAL_COMPLETE,
notes = "",
@@ -755,11 +734,12 @@
p.load(new TestInputStream());
fail("expected IOException");
} catch (IOException e) {
- // ok
+ // expected
}
-
}
+ // END android-added
+ // BEGIN android-added
protected byte[] writeProperties() {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(bout);
@@ -769,34 +749,9 @@
ps.close();
return bout.toByteArray();
}
+ // END android-added
- class MyProvider extends Provider {
- // private Set<Provider.Service> services = null;
-
- MyProvider() {
- super("MyProvider", 1.0, "Provider for testing");
- put("MessageDigest.ASH-1", "SomeClassName");
- put("MessageDigest.abc", "SomeClassName");
- put("Alg.Alias.MessageDigest.ASH1", "ASH-1");
- }
-
- MyProvider(String name, double version, String info) {
- super(name, version, info);
- }
-
- public void putService(Provider.Service s) {
- super.putService(s);
- }
-
- public void removeService(Provider.Service s) {
- super.removeService(s);
- }
-
- public int getNumServices() {
- return getServices().size();
- }
- }
-
+ // BEGIN android-added
static class TestSecurityManager extends SecurityManager {
boolean called = false;
private final String permissionName;
@@ -814,4 +769,5 @@
}
}
}
+ // END android-added
}
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Security2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Security2Test.java
index 49a0365..a59ada5 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Security2Test.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Security2Test.java
@@ -358,4 +358,4 @@
Security.removeProvider(entrust.getName());
}
}
-}
\ No newline at end of file
+}
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/SecurityTest.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/SecurityTest.java
index c03afc5..aa4c71b 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/SecurityTest.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/SecurityTest.java
@@ -205,9 +205,7 @@
}
assertEquals("Providers not removed", 0,
Security.getProviders().length);
- } catch (Exception e) {
- e.printStackTrace();
- } finally { // restore providers
+ } finally { // restore providers
for (int i = 0; i < providers.length; i++) {
Security.addProvider(providers[i]);
}
@@ -453,6 +451,9 @@
fail("No expected NullPointerException.");
} catch (NullPointerException e) {
}
+
+ Security.setProperty("myprop","test white space ");
+ assertEquals("test white space", Security.getProperty("myprop"));
}
/**
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Signature2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Signature2Test.java
index 20bc4b1..a657f60 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Signature2Test.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/Signature2Test.java
@@ -39,6 +39,7 @@
import java.security.cert.Certificate;
import java.security.spec.DSAParameterSpec;
import java.util.HashSet;
+import java.util.Locale;
import java.util.Set;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/SignatureException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/SignatureException2Test.java
deleted file mode 100644
index 9a6209a..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/SignatureException2Test.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.harmony.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargetNew;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-
-import java.security.SignatureException;
-
-@TestTargetClass(SignatureException.class)
-public class SignatureException2Test extends junit.framework.TestCase {
-
- /**
- * @tests java.security.SignatureException#SignatureException()
- */
- @TestTargetNew(
- level = TestLevel.COMPLETE,
- notes = "",
- method = "SignatureException",
- args = {}
- )
- public void test_Constructor() {
- // Test for method java.security.SignatureException()
- SignatureException e = new SignatureException();
- assertEquals("Failed toString test for constructed instance", "java.security.SignatureException", e
- .toString());
- }
-
- /**
- * @tests java.security.SignatureException#SignatureException(java.lang.String)
- */
- @TestTargetNew(
- level = TestLevel.PARTIAL,
- notes = "Verification with null string parameter missed",
- method = "SignatureException",
- args = {java.lang.String.class}
- )
- public void test_ConstructorLjava_lang_String() {
- // Test for method java.security.SignatureException(java.lang.String)
- SignatureException e = new SignatureException("test message");
- assertEquals("Failed toString test for constructed instance",
- "java.security.SignatureException: test message", e
- .toString());
- }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/SignedObjectTest.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/SignedObjectTest.java
index 77f341b..89d872e 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/SignedObjectTest.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/SignedObjectTest.java
@@ -15,11 +15,6 @@
* limitations under the License.
*/
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
package org.apache.harmony.security.tests.java.security;
import dalvik.annotation.TestLevel;
@@ -27,6 +22,11 @@
import dalvik.annotation.TestTargetNew;
import dalvik.annotation.TestTargets;
+import java.security.NoSuchAlgorithmException;
+import java.security.Signature;
+import java.security.SignedObject;
+import java.util.Properties;
+
import junit.framework.TestCase;
import org.apache.harmony.security.tests.support.TestKeyPair;
@@ -47,7 +47,6 @@
@TestTargetClass(SignedObject.class)
/**
* Tests for <code>SignedObject</code> constructor and methods
- *
*/
public class SignedObjectTest extends TestCase {
@@ -83,17 +82,11 @@
args = {java.security.PublicKey.class, java.security.Signature.class}
)
})
- public void testSignedObject() {
- Signature sig = null;
+ public void testSignedObject() throws Exception {
TestKeyPair tkp = null;
Properties prop;
-
- try {
- sig = Signature.getInstance("SHA1withDSA");
- } catch (NoSuchAlgorithmException e) {
- fail(e.toString());
- }
-
+ Signature sig = Signature.getInstance("SHA1withDSA");
+
try {
tkp = new TestKeyPair("DSA");
} catch (NoSuchAlgorithmException e) {
@@ -102,133 +95,14 @@
}
prop = new Properties();
prop.put("aaa", "bbb");
- SignedObject so = null;
- try {
- so = new SignedObject(prop, tkp.getPrivate(), sig);
- } catch (IOException e) {
- fail(e.toString());
- } catch (SignatureException e) {
- fail(e.toString());
- } catch (InvalidKeyException e) {
- fail(e.toString());
- } catch (InvalidKeySpecException e) {
- fail(e.toString());
- }
+
+ SignedObject so = new SignedObject(prop, tkp.getPrivate(), sig);
assertEquals("SHA1withDSA", so.getAlgorithm());
-
- try {
- assertEquals(so.getObject(), prop);
- } catch (ClassNotFoundException e) {
- fail(e.toString());
- } catch (IOException e) {
- fail(e.toString());
- }
- try {
- if (!so.verify(tkp.getPublic(), sig)) {
- fail("verify() failed");
- }
- } catch (SignatureException e) {
- fail(e.toString());
- } catch (InvalidKeyException e) {
- fail(e.toString());
- } catch (InvalidKeySpecException e) {
- fail(e.toString());
- }
-
- if (so.getSignature() == null) {
- fail("signature is null");
- }
-
- try {
- TestKeyPair tkp2 = new TestKeyPair("DH");
- so = new SignedObject(prop, tkp2.getPrivate(), sig);
- } catch(InvalidKeyException e) {
- // ok
- } catch (NoSuchAlgorithmException e) {
- fail(e.toString());
- } catch (SignatureException e) {
- fail(e.toString());
- } catch (InvalidKeySpecException e) {
- fail(e.toString());
- } catch (IOException e) {
- fail(e.toString());
- }
-
- try {
- new SignedObject(new Serializable() {
- private void writeObject(ObjectOutputStream out) throws IOException {
- throw new IOException();
- }
- }, tkp.getPrivate(), sig);
- } catch(InvalidKeyException e) {
- fail(e.toString());
- } catch (SignatureException e) {
- fail(e.toString());
- } catch (InvalidKeySpecException e) {
- fail(e.toString());
- } catch (IOException e) {
- // ok
- }
+ assertEquals(prop, so.getObject());
-
- try {
- new SignedObject(prop, tkp.getPrivate(), new Signature("TST") {
-
- @Override
- protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
- throw new SignatureException();
- }
-
- @Override
- protected void engineUpdate(byte[] b, int off, int len)
- throws SignatureException {
- throw new SignatureException();
- }
-
- @Override
- protected void engineUpdate(byte b) throws SignatureException {
- throw new SignatureException();
- }
-
- @Override
- protected byte[] engineSign() throws SignatureException {
- throw new SignatureException();
- }
-
- @Override
- protected void engineSetParameter(String param, Object value)
- throws InvalidParameterException {
-
- }
-
- @Override
- protected void engineInitVerify(PublicKey publicKey)
- throws InvalidKeyException {
-
- }
-
- @Override
- protected void engineInitSign(PrivateKey privateKey)
- throws InvalidKeyException {
-
- }
-
- @Override
- protected Object engineGetParameter(String param)
- throws InvalidParameterException {
- return null;
- }
- });
- } catch(InvalidKeyException e) {
- fail(e.toString());
- } catch (SignatureException e) {
- // ok
- } catch (InvalidKeySpecException e) {
- fail(e.toString());
- } catch (IOException e) {
- fail(e.toString());
- }
-
+ assertTrue("verify() failed", so.verify(tkp.getPublic(), sig));
+
+ assertNotNull("signature is null", so.getSignature());
}
}
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/TimestampTest.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/TimestampTest.java
index c3414f4..1015521 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/TimestampTest.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/TimestampTest.java
@@ -118,7 +118,7 @@
args = {}
)
public void testGetTimestamp() {
- Timestamp t = new Timestamp(now, cpath);
+ Timestamp t = new Timestamp(now, cpath);
assertEquals(now, t.getTimestamp());
assertNotSame(now, t.getTimestamp());
}
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/UnrecoverableKeyException2Test.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/UnrecoverableKeyException2Test.java
deleted file mode 100644
index ce97d60..0000000
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/UnrecoverableKeyException2Test.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.harmony.security.tests.java.security;
-
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargetNew;
-import dalvik.annotation.TestTargets;
-import dalvik.annotation.TestLevel;
-
-import java.security.UnrecoverableKeyException;
-
-@TestTargetClass(UnrecoverableKeyException.class)
-public class UnrecoverableKeyException2Test extends junit.framework.TestCase {
-
- /**
- * @tests java.security.UnrecoverableKeyException#UnrecoverableKeyException()
- */
- @TestTargetNew(
- level = TestLevel.COMPLETE,
- notes = "",
- method = "UnrecoverableKeyException",
- args = {}
- )
- public void test_Constructor() {
- // Test for method java.security.UnrecoverableKeyException()
- UnrecoverableKeyException e = new UnrecoverableKeyException();
- assertEquals("Failed toString test for constructed instance", "java.security.UnrecoverableKeyException", e
- .toString());
- }
-
- /**
- * @tests java.security.UnrecoverableKeyException#UnrecoverableKeyException(java.lang.String)
- */
- @TestTargetNew(
- level = TestLevel.PARTIAL,
- notes = "Verification with null string parameter missed",
- method = "UnrecoverableKeyException",
- args = {java.lang.String.class}
- )
- public void test_ConstructorLjava_lang_String() {
- // Test for method
- // java.security.UnrecoverableKeyException(java.lang.String)
- UnrecoverableKeyException e = new UnrecoverableKeyException(
- "test message");
- assertEquals("Failed toString test for constructed instance",
- "java.security.UnrecoverableKeyException: test message", e
- .toString());
- }
-}
\ No newline at end of file
diff --git a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.java b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.java
index ce02e9d..d03b43d 100644
--- a/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.java
+++ b/libcore/security/src/test/java/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.java
@@ -42,6 +42,11 @@
import tests.util.SerializationTester;
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
+
+import tests.util.SerializationTester;
+
import junit.framework.TestCase;
@TestTargetClass(UnresolvedPermission.class)
@@ -111,7 +116,6 @@
assertFalse(up.implies(new AllPermission()));
assertFalse(up.implies(new SecurityPermission("a.b.c")));
}
-
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
@@ -134,7 +138,6 @@
assertEquals("actions", deserializedUp.getUnresolvedActions());
assertNull(deserializedUp.getUnresolvedCerts());
}
-
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
@@ -155,14 +158,11 @@
assertEquals("java.security.SecurityPermission", deserializedUp
.getUnresolvedType());
assertEquals("a.b.c", deserializedUp.getUnresolvedName());
- assertEquals("action", deserializedUp.getUnresolvedActions());
- Certificate[] certs = deserializedUp.getUnresolvedCerts();
- assertNotNull(certs);
- assertEquals(1, certs.length);
+ assertEquals("actions", deserializedUp.getUnresolvedActions());
+ assertNull(deserializedUp.getUnresolvedCerts());
}
});
}
-
@TestTargetNew(
level = TestLevel.COMPLETE,
notes = "",
diff --git a/libcore/security/src/test/java/tests/api/java/security/PermissionCollectionTest.java b/libcore/security/src/test/java/tests/api/java/security/PermissionCollectionTest.java
index f36f119..267923a 100644
--- a/libcore/security/src/test/java/tests/api/java/security/PermissionCollectionTest.java
+++ b/libcore/security/src/test/java/tests/api/java/security/PermissionCollectionTest.java
@@ -28,6 +28,8 @@
import java.util.StringTokenizer;
import tests.support.Support_Exec;
+import static tests.support.Support_Exec.javaProcessBuilder;
+import static tests.support.Support_Exec.execAndGetOutput;
import tests.support.Support_GetLocal;
import tests.support.resource.Support_Resources;
import dalvik.annotation.KnownFailure;
@@ -168,17 +170,14 @@
}
}
- String classPath = new File(classURL.getFile()).getPath();
-
- // Execute Support_PermissionCollection in another VM
- String[] classPathArray = new String[2];
- classPathArray[0] = classPath;
- classPathArray[1] = jarFile.getPath();
- String[] args = { "-Djava.security.policy=" + policyFile.toURL(),
- "tests.support.Support_PermissionCollection",
- signedBKS.toExternalForm() };
-
- String result = Support_Exec.execJava(args, classPathArray, true);
+ ProcessBuilder builder = javaProcessBuilder();
+ builder.command().add("-cp");
+ builder.command().add(Support_Exec.createPath(
+ new File(classURL.getFile()).getPath(), jarFile.getPath()));
+ builder.command().add("-Djava.security.policy=" + policyFile.toURL());
+ builder.command().add("tests.support.Support_PermissionCollection");
+ builder.command().add(signedBKS.toExternalForm());
+ String result = execAndGetOutput(builder);
StringTokenizer resultTokenizer = new StringTokenizer(result, ",");
@@ -266,6 +265,7 @@
"testing permissionCollection-isREadOnly");
assertNotNull("toString should have returned a string of elements",
permi.newPermissionCollection().toString());
+ assertTrue(permi.newPermissionCollection().toString().endsWith("\n"));
}
// FIXME move me to Support_Resources
diff --git a/libcore/security/src/test/resources/serialization/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.golden.ser b/libcore/security/src/test/resources/serialization/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.golden.ser
index 2937f2f..931ee3f 100755
--- a/libcore/security/src/test/resources/serialization/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.golden.ser
+++ b/libcore/security/src/test/resources/serialization/org/apache/harmony/security/tests/java/security/UnresolvedPermissionTest.golden.ser
Binary files differ
diff --git a/libcore/sql/src/main/native/sqlite_jni.c b/libcore/sql/src/main/native/sqlite_jni.c
index 4923869..1a23769 100644
--- a/libcore/sql/src/main/native/sqlite_jni.c
+++ b/libcore/sql/src/main/native/sqlite_jni.c
@@ -1,3 +1,5 @@
+#include "JNIHelp.h"
+
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -276,23 +278,13 @@
static void
throwex(JNIEnv *env, const char *msg)
{
- jclass except = (*env)->FindClass(env, "SQLite/Exception");
-
- (*env)->ExceptionClear(env);
- if (except) {
- (*env)->ThrowNew(env, except, msg);
- }
+ jniThrowException(env, "SQLite/Exception", msg);
}
static void
throwoom(JNIEnv *env, const char *msg)
{
- jclass except = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
-
- (*env)->ExceptionClear(env);
- if (except) {
- (*env)->ThrowNew(env, except, msg);
- }
+ jniThrowException(env, "java/lang/OutOfMemoryError", msg);
}
static void
@@ -305,12 +297,7 @@
static void
throwioex(JNIEnv *env, const char *msg)
{
- jclass except = (*env)->FindClass(env, "java/io/IOException");
-
- (*env)->ExceptionClear(env);
- if (except) {
- (*env)->ThrowNew(env, except, msg);
- }
+ jniThrowException(env, "java/io/IOException", msg);
}
#endif
@@ -331,16 +318,10 @@
dest->result = 0;
dest->tofree = 0;
if (haveutf) {
- const char *utf = (*env)->GetStringUTFChars(env, src, 0);
-
- if (!utf) {
- return dest->result;
- }
- dest->tofree = malloc(strlen(utf) + 1);
- dest->result = dest->tofree;
- strcpy(dest->result, utf);
- (*env)->ReleaseStringUTFChars(env, src, utf);
- return dest->result;
+ const jsize utfLength = (*env)->GetStringUTFLength(env, src);
+ dest->result = dest->tofree = malloc(utfLength + 1);
+ (*env)->GetStringUTFRegion(env, src, 0, utfLength, dest->result);
+ return dest->result;
}
if (enc) {
bytes = (*env)->CallObjectMethod(env, src,
@@ -1331,11 +1312,10 @@
}
if (h) {
if (h->sqlite) {
- jboolean b;
jthrowable exc;
int rc = SQLITE_ERROR, nargs, i;
char *err = 0, *p;
- const char *str = (*env)->GetStringUTFChars(env, sql, &b);
+ const char *str = (*env)->GetStringUTFChars(env, sql, NULL);
transstr sqlstr;
struct args {
char *arg;
@@ -3009,10 +2989,9 @@
hvm *v;
jvalue vv;
jthrowable exc;
- jboolean b;
int rc = SQLITE_ERROR, nargs, i;
char *p;
- const char *str = (*env)->GetStringUTFChars(env, sql, &b);
+ const char *str = (*env)->GetStringUTFChars(env, sql, NULL);
const char *tail;
transstr sqlstr;
struct args {
@@ -3401,7 +3380,7 @@
return;
}
len16 = len16 + sizeof (jchar) - ((char *) tail - (char *) sql16);
- if (len16 < sizeof (jchar)) {
+ if (len16 < (jsize) sizeof (jchar)) {
len16 = sizeof (jchar);
}
v = malloc(sizeof (hvm) + len16);
@@ -3674,19 +3653,16 @@
return;
}
if (val) {
- len = (*env)->GetStringLength(env, val);
+ const jsize charCount = (*env)->GetStringLength(env, val);
+ len = charCount * sizeof(jchar);
if (len > 0) {
- const jchar *ch;
-
- len *= sizeof (jchar);
data = sqlite3_malloc(len);
if (!data) {
throwoom(env, "unable to get blob parameter");
return;
}
- ch = (*env)->GetStringChars(env, val, 0);
- memcpy(data, ch, len);
- (*env)->ReleaseStringChars(env, val, ch);
+
+ (*env)->GetStringRegion(env, val, 0, charCount, (jchar*) data);
ret = sqlite3_bind_text16((sqlite3_stmt *) v->vm,
pos, data, len, sqlite3_free);
} else {
diff --git a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DriverManagerTest.java b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DriverManagerTest.java
index 68ac6c5..ebb055c 100644
--- a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DriverManagerTest.java
+++ b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DriverManagerTest.java
@@ -19,12 +19,10 @@
import dalvik.annotation.KnownFailure;
import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
import dalvik.annotation.TestLevel;
import dalvik.annotation.TestTargetNew;
import java.io.ByteArrayOutputStream;
-import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Method;
@@ -37,9 +35,11 @@
import java.sql.SQLPermission;
import java.util.Enumeration;
import java.util.Properties;
-import tests.support.Support_Exec;
import junit.framework.TestCase;
+import static tests.support.Support_Exec.javaProcessBuilder;
+import static tests.support.Support_Exec.execAndGetOutput;
+
@TestTargetClass(DriverManager.class)
/**
* JUnit Testcase for the java.sql.DriverManager class
@@ -715,10 +715,9 @@
* Regression for HARMONY-4303
*/
public void test_initClass() throws Exception {
- String[] arg = new String[1];
- arg[0] = "org/apache/harmony/sql/tests/java/sql/TestMainForDriver";
- String result = Support_Exec.execJava(arg, null, true);
- assertEquals("", result);
+ ProcessBuilder builder = javaProcessBuilder();
+ builder.command().add("org/apache/harmony/sql/tests/java/sql/TestMainForDriver");
+ assertEquals("", execAndGetOutput(builder));
}
private static class BadDummyDriver extends DummyDriver {
diff --git a/libcore/support/src/test/java/tests/support/Support_Exec.java b/libcore/support/src/test/java/tests/support/Support_Exec.java
index c3a5ccc..7b92d0d 100644
--- a/libcore/support/src/test/java/tests/support/Support_Exec.java
+++ b/libcore/support/src/test/java/tests/support/Support_Exec.java
@@ -17,204 +17,115 @@
package tests.support;
-import java.io.ByteArrayOutputStream;
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
-import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.StringTokenizer;
-
-import junit.framework.TestCase;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.util.Arrays;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
public class Support_Exec extends TestCase {
- static final boolean againstDalvik;
- static {
- String platform = System.getProperty("java.vendor");
- againstDalvik = (platform.contains("Android"));
- }
+ private static final boolean againstDalvik
+ = System.getProperty("java.vendor").contains("Android");
/**
- * This function returns the output of the process as a string
+ * Returns a builder configured with the appropriate VM ("dalvikvm" or
+ * "java") and arguments (as specified by the system property
+ * {@code hy.test.vmargs}).
*/
- public static String execJava(String[] args, String[] classpath,
- boolean displayOutput) throws IOException, InterruptedException {
- Object[] arr =
- execJavaCommon(args, classpath, null, displayOutput, true);
-
- return getProcessOutput(arr, displayOutput);
- }
-
- /**
- * This function returns the output of the process as a string
- */
- public static String execJava(String[] args, String[] classpath, String[] envp,
- boolean displayOutput) throws IOException, InterruptedException {
- Object[] arr =
- execJavaCommon(args, classpath, envp, displayOutput, false);
-
- return getProcessOutput(arr, displayOutput);
- }
-
- public static String getProcessOutput(Object[] arr, boolean displayOutput)
+ public static ProcessBuilder javaProcessBuilder()
throws IOException, InterruptedException {
- Process proc = (Process) arr[0];
- StringBuilder output = new StringBuilder();
- InputStream in = proc.getInputStream();
- int result;
- byte[] bytes = new byte[1024];
-
- while ((result = in.read(bytes)) != -1) {
- output.append(new String(bytes, 0, result));
-
- if (displayOutput) {
- System.out.write(bytes, 0, result);
- }
- }
-
- in.close();
- proc.waitFor();
- checkStderr(arr);
- proc.destroy();
-
- return output.toString();
- }
-
- public static void checkStderr(Object[] execArgs) {
- StringBuilder errBuf = (StringBuilder) execArgs[1];
-
- synchronized (errBuf) {
- if (errBuf.length() > 0) {
- fail(errBuf.toString());
- }
- }
- }
-
- public static Object[] execJava2(String[] args, String[] classpath,
- boolean displayOutput) throws IOException, InterruptedException {
- return execJavaCommon(args, classpath, null, displayOutput, true);
- }
-
- private static Object[] execJavaCommon(String[] args, String[] classpath,
- String[] envp, boolean displayOutput, boolean appendToSystemClassPath)
- throws IOException, InterruptedException {
- // this function returns the resulting process from the exec
- ArrayList<String> execArgs = null;
- StringBuilder classPathString = new StringBuilder();
- StringBuilder command;
- String executable;
- String testVMArgs;
- StringTokenizer st;
-
- execArgs = new ArrayList<String>(3 + args.length);
+ ProcessBuilder builder = new ProcessBuilder();
// construct the name of executable file
- if (againstDalvik) {
- execArgs.add("dalvikvm");
- } else {
- execArgs.add("java");
- }
-
- // add classpath string
- if (classpath != null) {
- for (String element : classpath) {
- classPathString.append(File.pathSeparator);
- classPathString.append(element);
- }
- }
- if (appendToSystemClassPath) {
- execArgs.add("-cp");
- execArgs.add(System.getProperty("java.class.path") +
- classPathString);
- } else {
- if (classpath != null) {
- execArgs.add("-cp");
- execArgs.add(classPathString.toString());
- }
- }
+ builder.command().add(againstDalvik ? "dalvikvm" : "java");
// parse hy.test.vmargs if was given
- testVMArgs = System.getProperty("hy.test.vmargs");
+ String testVMArgs = System.getProperty("hy.test.vmargs");
if (testVMArgs != null) {
- st = new StringTokenizer(testVMArgs, " ");
-
- while (st.hasMoreTokens()) {
- execArgs.add(st.nextToken());
- }
+ builder.command().addAll(Arrays.asList(testVMArgs.split("\\s+")));
}
- // add custom args given as parameter
- for (String arg : args) {
- execArgs.add(arg);
- }
-
- if (displayOutput) {
- // Construct command line string and print it to stdout.
- command = new StringBuilder(execArgs.get(0));
- for (int i = 1; i < execArgs.size(); i++) {
- command.append(" ");
- command.append(execArgs.get(i));
- }
- }
-
- // execute java process
- return execAndDigestOutput(execArgs.toArray(new String[execArgs.size()]), envp);
+ return builder;
}
- //
- // mc: This looks like functionaly worth publicity:
- //
- public static Object[] execAndDigestOutput (String[] cmdLine, String[] envp)
- throws IOException, InterruptedException {
+ /**
+ * Returns a command-line ready path formed by joining the path elements
+ * with the system path separator as a separator.
+ */
+ public static String createPath(String... elements) {
+ StringBuilder result = new StringBuilder();
+ for (String element : elements) {
+ result.append(File.pathSeparator);
+ result.append(element);
+ }
+ return result.toString();
+ }
-// System.out.println("Commandline BEGIN");
-// for (int i = 0; i < cmdLine.length; i++) {
-// System.out.println(cmdLine[i]);
-// }
-// System.out.println("END");
+ /**
+ * Starts the specified process, collects its output from standard out and
+ * standard err, and returns. If the stream emits anything to standard err,
+ * an AssertionFailedError will be thrown.
+ *
+ * <p>This method assumes the target process will complete within ten
+ * seconds. If it does not, an AssertionFailedError will be thrown.
+ */
+ public static String execAndGetOutput(ProcessBuilder builder)
+ throws IOException {
+ Process process = builder.start();
+ ExecutorService executorService = Executors.newFixedThreadPool(2);
+ try {
+ Future<String> errFuture = executorService.submit(
+ streamToStringCallable(process.getErrorStream()));
+ Future<String> outFuture = executorService.submit(
+ streamToStringCallable(process.getInputStream()));
- final Process proc = Runtime.getRuntime().exec(cmdLine, envp);
- final StringBuilder errBuf = new StringBuilder();
+ Throwable failure;
+ String out = "";
+ try {
+ out = outFuture.get(10, TimeUnit.SECONDS);
+ String err = errFuture.get(10, TimeUnit.SECONDS);
+ failure = err.length() > 0
+ ? new AssertionFailedError("Unexpected err stream data:\n" + err)
+ : null;
+ } catch (Exception e) {
+ failure = e;
+ }
- Thread errThread = new Thread(new Runnable() {
- public void run() {
- synchronized (errBuf) {
- InputStream err;
- int result;
- byte[] bytes = new byte[1024];
+ if (failure != null) {
+ AssertionFailedError error = new AssertionFailedError(
+ "Failed to execute " + builder.command() + "; output was:\n" + out);
+ error.initCause(failure);
+ throw error;
+ } else {
+ return out;
+ }
+ } finally {
+ executorService.shutdown();
+ }
+ }
- synchronized (proc) {
- proc.notifyAll();
- }
-
- err = proc.getErrorStream();
- try {
- while ((result = err.read(bytes)) != -1) {
- System.err.write(bytes, 0, result);
- errBuf.append(new String(bytes));
- }
- err.close();
- } catch (IOException e) {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- PrintStream printer = new PrintStream(out);
-
- e.printStackTrace();
- e.printStackTrace(printer);
- printer.close();
- errBuf.append(new String(out.toByteArray()));
- }
+ private static Callable<String> streamToStringCallable(final InputStream in) {
+ return new Callable<String>() {
+ public String call() throws Exception {
+ StringWriter writer = new StringWriter();
+ Reader reader = new InputStreamReader(in);
+ int c;
+ while ((c = reader.read()) != -1) {
+ writer.write(c);
}
+ return writer.toString();
}
- });
-
- synchronized (proc) {
- errThread.start();
- // wait for errThread to start
- proc.wait();
- }
-
- return new Object[] { proc, errBuf };
+ };
}
-
}
diff --git a/libcore/text/src/main/java/java/text/BreakIterator.java b/libcore/text/src/main/java/java/text/BreakIterator.java
index 7d19179..3a08427 100644
--- a/libcore/text/src/main/java/java/text/BreakIterator.java
+++ b/libcore/text/src/main/java/java/text/BreakIterator.java
@@ -23,6 +23,8 @@
import java.util.Locale;
+import org.apache.harmony.text.internal.nls.Messages;
+
/**
* Locates boundaries in text. This class defines a protocol for objects that
* break up a piece of natural-language text according to a set of criteria.
@@ -542,11 +544,10 @@
* greater than the length of {@code buf}.
*/
protected static long getLong(byte[] buf, int offset) {
- if (null == buf) {
- throw new NullPointerException();
- }
- if (offset < 0 || buf.length - offset < LONG_LENGTH) {
- throw new ArrayIndexOutOfBoundsException();
+ // Force a buf null check first!
+ if (buf.length - offset < LONG_LENGTH || offset < 0) {
+ // text.1E=Offset out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("text.1E", offset)); //$NON-NLS-1$
}
long result = 0;
for (int i = offset; i < offset + LONG_LENGTH; i++) {
@@ -571,11 +572,10 @@
* greater than the length of {@code buf}.
*/
protected static int getInt(byte[] buf, int offset) {
- if (null == buf) {
- throw new NullPointerException();
- }
- if (offset < 0 || buf.length - INT_LENGTH < offset) {
- throw new ArrayIndexOutOfBoundsException();
+ // Force buf null check first!
+ if (buf.length - INT_LENGTH < offset || offset < 0) {
+ // text.1E=Offset out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("text.1E", offset)); //$NON-NLS-1$
}
int result = 0;
for (int i = offset; i < offset + INT_LENGTH; i++) {
@@ -600,11 +600,10 @@
* greater than the length of {@code buf}.
*/
protected static short getShort(byte[] buf, int offset) {
- if (null == buf) {
- throw new NullPointerException();
- }
- if (offset < 0 || buf.length - SHORT_LENGTH < offset) {
- throw new ArrayIndexOutOfBoundsException();
+ // Force buf null check first!
+ if (buf.length - SHORT_LENGTH < offset || offset < 0) {
+ // text.1E=Offset out of bounds \: {0}
+ throw new ArrayIndexOutOfBoundsException(Messages.getString("text.1E", offset)); //$NON-NLS-1$
}
short result = 0;
for (int i = offset; i < offset + SHORT_LENGTH; i++) {
diff --git a/libcore/text/src/main/java/java/text/Collator.java b/libcore/text/src/main/java/java/text/Collator.java
index aaa3e12..71ebb94 100644
--- a/libcore/text/src/main/java/java/text/Collator.java
+++ b/libcore/text/src/main/java/java/text/Collator.java
@@ -22,12 +22,11 @@
package java.text;
import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.Comparator;
import java.util.Locale;
import java.util.Vector;
-import org.apache.harmony.luni.util.PriviAction;
-
/**
* Performs locale-sensitive string comparison. A concrete subclass,
* {@link RuleBasedCollator}, allows customization of the collation ordering by
@@ -163,7 +162,11 @@
static {
// CACHE_SIZE includes key and value, so needs to be double
String cacheSize = AccessController
- .doPrivileged(new PriviAction<String>("collator.cache")); //$NON-NLS-1$
+ .doPrivileged(new PrivilegedAction<String>() {
+ public String run() {
+ return System.getProperty("collator.cache"); //$NON-NLS-1$
+ }
+ });
if (cacheSize != null) {
try {
CACHE_SIZE = Integer.parseInt(cacheSize);
diff --git a/libcore/text/src/main/java/java/text/DateFormat.java b/libcore/text/src/main/java/java/text/DateFormat.java
index f39965a..531bed8 100644
--- a/libcore/text/src/main/java/java/text/DateFormat.java
+++ b/libcore/text/src/main/java/java/text/DateFormat.java
@@ -666,7 +666,7 @@
public Date parse(String string) throws ParseException {
ParsePosition position = new ParsePosition(0);
Date date = parse(string, position);
- if (position.getErrorIndex() != -1 || position.getIndex() == 0) {
+ if (position.getIndex() == 0) {
// text.19=Unparseable date: {0}
throw new ParseException(
Messages.getString("text.19", string), position.getErrorIndex()); //$NON-NLS-1$
diff --git a/libcore/text/src/main/java/java/text/Format.java b/libcore/text/src/main/java/java/text/Format.java
index 6ee1ba2..3a6e49d 100644
--- a/libcore/text/src/main/java/java/text/Format.java
+++ b/libcore/text/src/main/java/java/text/Format.java
@@ -202,8 +202,10 @@
public Object parseObject(String string) throws ParseException {
ParsePosition position = new ParsePosition(0);
Object result = parseObject(string, position);
- if (position.getErrorIndex() != -1 || position.getIndex() == 0) {
- throw new ParseException(null, position.getErrorIndex());
+ if (position.getIndex() == 0) {
+ // text.1C=Format.parseObject(String) parse failure
+ throw new ParseException(
+ Messages.getString("text.1C"), position.getErrorIndex()); //$NON-NLS-1$
}
return result;
}
diff --git a/libcore/text/src/main/java/java/text/MessageFormat.java b/libcore/text/src/main/java/java/text/MessageFormat.java
index 4ab1ade..f6074b2 100644
--- a/libcore/text/src/main/java/java/text/MessageFormat.java
+++ b/libcore/text/src/main/java/java/text/MessageFormat.java
@@ -859,8 +859,10 @@
public Object[] parse(String string) throws ParseException {
ParsePosition position = new ParsePosition(0);
Object[] result = parse(string, position);
- if (position.getErrorIndex() != -1 || position.getIndex() == 0) {
- throw new ParseException(null, position.getErrorIndex());
+ if (position.getIndex() == 0) {
+ // text.1B=MessageFormat.parseObject(String) parse failure
+ throw new ParseException(
+ Messages.getString("text.1B"), position.getErrorIndex()); //$NON-NLS-1$
}
return result;
}
diff --git a/libcore/text/src/main/java/java/text/NumberFormat.java b/libcore/text/src/main/java/java/text/NumberFormat.java
index 5b8d883..87f17c1 100644
--- a/libcore/text/src/main/java/java/text/NumberFormat.java
+++ b/libcore/text/src/main/java/java/text/NumberFormat.java
@@ -555,8 +555,10 @@
public Number parse(String string) throws ParseException {
ParsePosition pos = new ParsePosition(0);
Number number = parse(string, pos);
- if (pos.getErrorIndex() != -1 || pos.getIndex() == 0) {
- throw new ParseException(null, pos.getErrorIndex());
+ if (pos.getIndex() == 0) {
+ // text.1D=Unparseable number: {0}
+ throw new ParseException(
+ Messages.getString("text.1D", string), pos.getErrorIndex()); //$NON-NLS-1$
}
return number;
}
diff --git a/libcore/text/src/main/java/org/apache/harmony/text/internal/nls/messages.properties b/libcore/text/src/main/java/org/apache/harmony/text/internal/nls/messages.properties
index 22221a9..b80cde2 100644
--- a/libcore/text/src/main/java/org/apache/harmony/text/internal/nls/messages.properties
+++ b/libcore/text/src/main/java/org/apache/harmony/text/internal/nls/messages.properties
@@ -43,4 +43,7 @@
text.18=Not a valid {0}, subclass should override readResolve()
text.19=Unparseable date: {0}
text.1A=position is null
-
+text.1B=MessageFormat.parseObject(String) parse failure
+text.1C=Format.parseObject(String) parse failure
+text.1D=Unparseable number: {0}
+text.1E=Offset out of bounds \: {0}
diff --git a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatTest.java b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatTest.java
index aa36abc..2b8c267 100644
--- a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatTest.java
+++ b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatTest.java
@@ -78,6 +78,29 @@
String result;
char current;
+ // For BigDecimal with multiplier test.
+ DecimalFormat df = new DecimalFormat();
+ df.setMultiplier(10);
+ iterator = df.formatToCharacterIterator(new BigDecimal("12345678901234567890"));
+ result = "123,456,789,012,345,678,900";
+ current = iterator.current();
+ for (int i = 0; i < result.length(); i++) {
+ assertEquals("wrong char @" + i, result.charAt(i), current);
+ current = iterator.next();
+ }
+
+ // For BigDecimal with multiplier test.
+ df = new DecimalFormat();
+ df.setMultiplier(-1);
+ df.setMaximumFractionDigits(20);
+ iterator = df.formatToCharacterIterator(new BigDecimal("1.23456789012345678901"));
+ result = "-1.23456789012345678901";
+ current = iterator.current();
+ for (int i = 0; i < result.length(); i++) {
+ assertEquals("wrong char @" + i, result.charAt(i), current);
+ current = iterator.next();
+ }
+
iterator = new DecimalFormat()
.formatToCharacterIterator(new BigDecimal("1.23456789E1234"));
runStarts = new int[] {0, 0, 2, 3, 3, 3, 6, 7, 7, 7, 10, 11, 11, 11, 14};
@@ -2547,4 +2570,119 @@
DecimalFormat format = (DecimalFormat) DecimalFormat.getInstance();
format.setDecimalFormatSymbols(null);
}
+
+ private void assertBigDecimalWithFraction(
+ BigDecimal bd,
+ String expectedResult,
+ int fraction) {
+ NumberFormat pf = NumberFormat.getPercentInstance();
+ pf.setMaximumFractionDigits(fraction);
+ assertEquals(expectedResult, pf.format(bd));
+ }
+
+ private void assertDecFmtWithMultiplierAndFraction(
+ String value,
+ int multiplier,
+ int fraction,
+ String expectedResult) {
+
+ DecimalFormat df = (DecimalFormat)NumberFormat.getInstance();
+ df.setMultiplier(multiplier);
+ df.setMaximumFractionDigits(fraction);
+ BigDecimal d = new BigDecimal(value);
+ assertEquals(expectedResult, df.format(d));
+ }
+
+ @TestTargetNew(
+ level = TestLevel.ADDITIONAL,
+ notes = "Regression test for some existing bugs and crashes",
+ method = "format",
+ args = { String.class, Object[].class }
+ )
+ public void testBigDecimalBug1897917() {
+ // Bug1897917 : BigDecimal does not take into account multiplier.
+ // So the BigDecimal 0.17 formatted in PercentInstance is 0% instead of 17%.
+
+ NumberFormat pf = NumberFormat.getPercentInstance();
+
+ // Test bug 1897917 case.
+ assertEquals("17%", pf.format(BigDecimal.valueOf(0.17)));
+
+ // Test long decimal formatted in PercentInstance with various fractions.
+ String longDec = "11.2345678901234567890123456789012345678901234567890";
+ BigDecimal bd = new BigDecimal(longDec);
+ assertBigDecimalWithFraction(bd, "1,123.46%", 2);
+ assertBigDecimalWithFraction(bd, "1,123.45678901%", 8);
+ assertBigDecimalWithFraction(bd, "1,123.4567890123%", 10);
+ assertBigDecimalWithFraction(bd, "1,123.45678901234567890123%", 20);
+ assertBigDecimalWithFraction(bd, "1,123.456789012345678901234567890123%", 30);
+
+ // Test trailing zeros.
+ assertDecFmtWithMultiplierAndFraction("3333.33333333", 3, 4, "10,000");
+ assertDecFmtWithMultiplierAndFraction("3333.33333333", -3, 4, "-10,000");
+ assertDecFmtWithMultiplierAndFraction("0.00333333", 3, 4, "0.01");
+ assertDecFmtWithMultiplierAndFraction("3330000000000000000000000000000000", 3, 4,
+ "9,990,000,000,000,000,000,000,000,000,000,000");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.ADDITIONAL,
+ notes = "Regression test for some existing bugs and crashes",
+ method = "format",
+ args = { String.class, Object[].class }
+ )
+ public void testBigDecimalTestBigIntWithMultiplier() {
+ // Big integer tests.
+ assertDecFmtWithMultiplierAndFraction("123456789012345", 10, 0, "1,234,567,890,123,450");
+ assertDecFmtWithMultiplierAndFraction("12345678901234567890", 10, 0,
+ "123,456,789,012,345,678,900");
+ assertDecFmtWithMultiplierAndFraction("98765432109876543210987654321", 10, 0,
+ "987,654,321,098,765,432,109,876,543,210");
+
+ assertDecFmtWithMultiplierAndFraction("123456789012345", -10, 0, "-1,234,567,890,123,450");
+ assertDecFmtWithMultiplierAndFraction("12345678901234567890", -10, 0,
+ "-123,456,789,012,345,678,900");
+ assertDecFmtWithMultiplierAndFraction("98765432109876543210987654321", -10, 0,
+ "-987,654,321,098,765,432,109,876,543,210");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.ADDITIONAL,
+ notes = "Regression test for some existing bugs and crashes",
+ method = "format",
+ args = { String.class, Object[].class }
+ )
+ public void testBigDecimalICUConsistency() {
+ DecimalFormat df = (DecimalFormat) NumberFormat.getInstance();
+ df.setMaximumFractionDigits(2);
+ df.setMultiplier(2);
+ assertEquals(df.format(BigDecimal.valueOf(0.16)),
+ df.format(BigDecimal.valueOf(0.16).doubleValue()));
+ assertEquals(df.format(BigDecimal.valueOf(0.0293)),
+ df.format(BigDecimal.valueOf(0.0293).doubleValue()));
+ assertEquals(df.format(BigDecimal.valueOf(0.006)),
+ df.format(BigDecimal.valueOf(0.006).doubleValue()));
+ assertEquals(df.format(BigDecimal.valueOf(0.00283)),
+ df.format(BigDecimal.valueOf(0.00283).doubleValue()));
+ assertEquals(df.format(BigDecimal.valueOf(1.60)),
+ df.format(BigDecimal.valueOf(1.60).doubleValue()));
+ assertEquals(df.format(BigDecimal.valueOf(15)),
+ df.format(BigDecimal.valueOf(15).doubleValue()));
+ assertEquals(df.format(BigDecimal.valueOf(170)),
+ df.format(BigDecimal.valueOf(170).doubleValue()));
+ assertEquals(df.format(BigDecimal.valueOf(234.56)),
+ df.format(BigDecimal.valueOf(234.56).doubleValue()));
+ assertEquals(df.format(BigDecimal.valueOf(0)),
+ df.format(BigDecimal.valueOf(0).doubleValue()));
+ assertEquals(df.format(BigDecimal.valueOf(-1)),
+ df.format(BigDecimal.valueOf(-1).doubleValue()));
+ assertEquals(df.format(BigDecimal.valueOf(-10000)),
+ df.format(BigDecimal.valueOf(-10000).doubleValue()));
+ assertEquals(df.format(BigDecimal.valueOf(-0.001)),
+ df.format(BigDecimal.valueOf(-0.001).doubleValue()));
+ assertEquals(df.format(BigDecimal.valueOf(1234567890.1234567)),
+ df.format(BigDecimal.valueOf(1234567890.1234567).doubleValue()));
+ assertEquals(df.format(BigDecimal.valueOf(1.234567E100)),
+ df.format(BigDecimal.valueOf(1.234567E100).doubleValue()));
+ }
}
diff --git a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/ParseExceptionTest.java b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/ParseExceptionTest.java
index 1c2da6a..3bcc38c 100644
--- a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/ParseExceptionTest.java
+++ b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/ParseExceptionTest.java
@@ -37,15 +37,13 @@
args = {java.lang.String.class, int.class}
)
public void test_ConstructorLjava_lang_StringI() {
- // Test for method java.text.ParseException(java.lang.String, int)
- // SM
try {
DateFormat df = DateFormat.getInstance();
df.parse("HelloWorld");
+ fail("ParseException not created/thrown.");
} catch (ParseException e) {
- return;
+ // expected
}
- fail("ParseException not created/thrown.");
}
/**
@@ -58,8 +56,6 @@
args = {}
)
public void test_getErrorOffset() {
- // Test for method int java.text.ParseException.getErrorOffset()
- // SM
try {
DateFormat df = DateFormat.getInstance();
df.parse("1999HelloWorld");
@@ -67,18 +63,4 @@
assertEquals("getErrorOffsetFailed.", 4, e.getErrorOffset());
}
}
-
- /**
- * Sets up the fixture, for example, open a network connection. This method
- * is called before a test is executed.
- */
- protected void setUp() {
- }
-
- /**
- * Tears down the fixture, for example, close a network connection. This
- * method is called after a test is executed.
- */
- protected void tearDown() {
- }
}
diff --git a/libcore/tools/integrate/Android.mk b/libcore/tools/integrate/Android.mk
index 629a5fd..f0f25b3 100644
--- a/libcore/tools/integrate/Android.mk
+++ b/libcore/tools/integrate/Android.mk
@@ -7,9 +7,9 @@
Filesystem.java \
Git.java \
Module.java \
- Modules.java \
MappedDirectory.java \
PullHarmonyCode.java \
+ PushAndroidCode.java \
Svn.java
LOCAL_MODULE:= integrate
diff --git a/libcore/tools/integrate/Filesystem.java b/libcore/tools/integrate/Filesystem.java
index a9c1789..4b296a0 100644
--- a/libcore/tools/integrate/Filesystem.java
+++ b/libcore/tools/integrate/Filesystem.java
@@ -32,11 +32,28 @@
* directory is nonempty.
*/
public int moveContents(String source, String target) {
+ return copyContents(true, source, target);
+ }
+
+ /**
+ * Copies all of the files in {@code source} to {@code target}, one at a
+ * time. Unlike {@code move}, this approach works even if the target
+ * directory is nonempty.
+ */
+ public int copyContents(String source, String target) {
+ return copyContents(false, source, target);
+ }
+
+ private int copyContents(boolean move, String source, String target) {
List<String> files = new Command("find", source, "-type", "f") .execute();
for (String file : files) {
String targetFile = target + "/" + file.substring(source.length());
mkdir(parent(targetFile));
- new Command("mv", "-i", file, targetFile).execute();
+ if (move) {
+ new Command("mv", "-i", file, targetFile).execute();
+ } else {
+ new Command("cp", file, targetFile).execute();
+ }
}
return files.size();
}
diff --git a/libcore/tools/integrate/Module.java b/libcore/tools/integrate/Module.java
index 5cb7035..63d35a2 100644
--- a/libcore/tools/integrate/Module.java
+++ b/libcore/tools/integrate/Module.java
@@ -14,7 +14,10 @@
* limitations under the License.
*/
+import java.util.Collections;
+import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
+import java.util.Map;
import java.util.Set;
/**
@@ -22,6 +25,47 @@
*/
class Module {
+ static final Map<String, Module> VALUES;
+ static {
+ Map<String, Module> valuesMutable = new LinkedHashMap<String, Module>();
+
+ String svnRoot = "http://svn.apache.org/repos/asf/harmony/enhanced/classlib/trunk/modules";
+ valuesMutable.put("archive", new Module.Builder(svnRoot, "archive")
+ .mapDirectory("archive/src/main/native/archive/shared",
+ "archive/src/main/native")
+ .mapDirectory("archive/src/main/native/zip/shared",
+ "archive/src/main/native")
+ .build());
+
+ valuesMutable.put("crypto", new Module.Builder(svnRoot, "crypto")
+ .mapDirectory("crypto/src/test/api/java.injected/javax",
+ "crypto/src/test/java/org/apache/harmony/crypto/tests/javax")
+ .mapDirectory("crypto/src/test/api/java",
+ "crypto/src/test/java")
+ .mapDirectory("crypto/src/test/resources/serialization",
+ "crypto/src/test/java/serialization")
+ .mapDirectory("crypto/src/test/support/common/java",
+ "crypto/src/test/java")
+ .build());
+
+ valuesMutable.put("regex", new Module.Builder(svnRoot, "regex").build());
+
+ valuesMutable.put("security", new Module.Builder(svnRoot, "security")
+ .mapDirectory("security/src/main/java/common",
+ "security/src/main/java")
+ .mapDirectory("security/src/main/java/unix/org",
+ "security/src/main/java/org")
+ .mapDirectory("security/src/test/api/java",
+ "security/src/test/java")
+ .build());
+
+ valuesMutable.put("text", new Module.Builder(svnRoot, "text").build());
+
+ valuesMutable.put("x-net", new Module.Builder(svnRoot, "x-net").build());
+
+ VALUES = Collections.unmodifiableMap(valuesMutable);
+ }
+
private final String svnBaseUrl;
private final String path;
private final Set<MappedDirectory> mappedDirectories;
diff --git a/libcore/tools/integrate/Modules.java b/libcore/tools/integrate/Modules.java
deleted file mode 100644
index 2475852..0000000
--- a/libcore/tools/integrate/Modules.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-/**
- * Constants that define modules shared by Harmony and Dalvik.
- */
-public class Modules {
-
- private static final String SVN_ROOT
- = "http://svn.apache.org/repos/asf/harmony/enhanced/classlib/trunk/modules";
-
- public static final Module ARCHIVE = new Module.Builder(SVN_ROOT, "archive")
- .mapDirectory("archive/src/main/native/archive/shared",
- "archive/src/main/native")
- .mapDirectory("archive/src/main/native/zip/shared",
- "archive/src/main/native")
- .build();
-
- public static final Module CRYPTO = new Module.Builder(SVN_ROOT, "crypto")
- .mapDirectory("crypto/src/test/api/java.injected/javax",
- "crypto/src/test/java/org/apache/harmony/crypto/tests/javax")
- .mapDirectory("crypto/src/test/api/java",
- "crypto/src/test/java")
- .mapDirectory("crypto/src/test/resources/serialization",
- "crypto/src/test/java/serialization")
- .mapDirectory("crypto/src/test/support/common/java",
- "crypto/src/test/java")
- .build();
-
- public static final Module REGEX
- = new Module.Builder(SVN_ROOT, "regex").build();
-
- public static final Module SECURITY = new Module.Builder(SVN_ROOT, "security")
- .mapDirectory("security/src/main/java/common",
- "security/src/main/java")
- .mapDirectory("security/src/main/java/unix/org",
- "security/src/main/java/org")
- .mapDirectory("security/src/test/api/java",
- "security/src/test/java")
- .build();
-
- public static final Module TEXT
- = new Module.Builder(SVN_ROOT, "text").build();
-
- public static final Module X_NET
- = new Module.Builder(SVN_ROOT, "x-net").build();
-
- // TODO: add the other modules
-}
diff --git a/libcore/tools/integrate/PullHarmonyCode.java b/libcore/tools/integrate/PullHarmonyCode.java
index 6710801..ce019d4 100644
--- a/libcore/tools/integrate/PullHarmonyCode.java
+++ b/libcore/tools/integrate/PullHarmonyCode.java
@@ -102,8 +102,61 @@
}
}
+
public static void main(String[] args) {
-// new PullHarmonyCode(527399, 802921).pull(Modules.CRYPTO);
- new PullHarmonyCode(772995, 802921).pull(Modules.ARCHIVE);
+ if (args.length < 3) {
+ printUsage();
+ return;
+ }
+
+ int currentSvnRev = Integer.parseInt(args[0]);
+ int targetSvnRev = Integer.parseInt(args[1]);
+
+ if (currentSvnRev < 527399 || targetSvnRev <= currentSvnRev) {
+ System.out.println("Invalid SVN revision range: "
+ + currentSvnRev + ".." + targetSvnRev);
+ return;
+ }
+
+ Module module = Module.VALUES.get(args[2]);
+ if (module == null) {
+ System.out.println("No such module: " + args[2]);
+ return;
+ }
+
+ PullHarmonyCode puller = new PullHarmonyCode(currentSvnRev, targetSvnRev);
+ puller.pull(module);
+ }
+
+ private static void printUsage() {
+ System.out.println("This tool will prepare a three-way merge between the latest Harmony");
+ System.out.println("the latest Dalvik, and their common ancestor. It downloads both old");
+ System.out.println("and new versions of Harmony code from SVN for better merge results.");
+ System.out.println();
+ System.out.println("Usage: PullHarmonyCode <current_rev> <target_rev> <module>...");
+ System.out.println();
+ System.out.println(" <current_rev> is the SVN revision of the Harmony code that was");
+ System.out.println(" most recently integrated into Dalvik. This should");
+ System.out.println(" be a number greater than 527399. The current");
+ System.out.println(" revision for each module is tracked at");
+ System.out.println(" http://go/dalvik/harmony");
+ System.out.println();
+ System.out.println(" <target_rev> is the SVN revision of the Harmony code to be");
+ System.out.println(" merged into Dalvik. This should be a number greater");
+ System.out.println(" than <current_rev>. The latest Harmony revision is");
+ System.out.println(" tracked at");
+ System.out.println(" http://svn.apache.org/viewvc/harmony/?root=Apache-SVN");
+ System.out.println();
+ System.out.println(" <module> is one of " + Module.VALUES.keySet());
+ System.out.println();
+ System.out.println("This program must be executed from within the dalvik/libcore directory");
+ System.out.println("of an Android git client. Such a client must be synced and contain no");
+ System.out.println("uncommitted changes. Upon termination, a new Git branch with the");
+ System.out.println("integrated changes will be active. This branch may require some manual");
+ System.out.println("merging.");
+ System.out.println();
+ System.out.println("Example usage:");
+ System.out.println(" java -cp ../../out/host/linux-x86/framework/integrate.jar PullAndroidCode \\");
+ System.out.println(" 527399 802921 security");
}
}
diff --git a/libcore/tools/integrate/PushAndroidCode.java b/libcore/tools/integrate/PushAndroidCode.java
new file mode 100644
index 0000000..c0002f5
--- /dev/null
+++ b/libcore/tools/integrate/PushAndroidCode.java
@@ -0,0 +1,87 @@
+// Copyright 2009 Google Inc. All Rights Reserved.
+
+import java.util.UUID;
+
+/**
+ * Copy the current Android sourcecode into Apache Harmony, where it can be
+ * reviewed and submitted to their SVN. Only run this script after first merging
+ * the latest harmony code into Android.
+ */
+public class PushAndroidCode {
+
+ private final String androidPath;
+ private final String harmonyPath;
+
+ public PushAndroidCode(String androidPath, String harmonyPath) {
+ this.androidPath = androidPath;
+ this.harmonyPath = harmonyPath;
+ }
+
+ public void push(Module module) {
+ Filesystem filesystem = new Filesystem();
+
+ // copy android code to a temp directory that is laid out like Harmony
+ String temp = "/tmp/" + UUID.randomUUID();
+ filesystem.mkdir(temp);
+ filesystem.copyContents(androidPath + "/" + module.path(),
+ temp + "/" + module.path());
+ for (MappedDirectory mappedDirectory : module.getMappedDirectories()) {
+ filesystem.moveContents(
+ temp + "/" + mappedDirectory.gitPath(),
+ temp + "/" + mappedDirectory.svnPath());
+ }
+
+ // clobber files from harmony with their Android equivalents
+ filesystem.copyContents(temp + "/" + module.path(),
+ harmonyPath + "/" + module.path());
+ }
+
+ public static void main(String[] args) {
+ if (args.length < 3) {
+ printUsage();
+ return;
+ }
+
+ String androidPath = args[0] + "/dalvik/libcore";
+ String harmonyPath = args[1] + "/working_classlib/modules";
+
+ // TODO: validate directories?
+
+ Module[] modules = new Module[args.length - 2];
+ for (int i = 0; i < modules.length; i++) {
+ modules[i] = Module.VALUES.get(args[i+2]);
+ if (modules[i] == null) {
+ System.out.println("No such module: " + args[i+2]);
+ return;
+ }
+ }
+
+ PushAndroidCode pusher = new PushAndroidCode(androidPath, harmonyPath);
+ for (Module module : modules) {
+ pusher.push(module);
+ }
+ }
+
+ private static void printUsage() {
+ System.out.println("This tool will clobber Harmony's core libraries with Android's copy");
+ System.out.println("so that a patch can be submitted upstream.");
+ System.out.println();
+ System.out.println("Usage: PushAndroidCode <android_root> <harmony_root> <module>...");
+ System.out.println();
+ System.out.println(" <android_root> is the android git client directory that contains dalvik");
+ System.out.println(" This should hold an up-to-date checkout of Android. The");
+ System.out.println(" target modules should also be up-to-date with respect to");
+ System.out.println(" Harmony; use the PullHarmonyCode tool first if necessary.");
+ System.out.println();
+ System.out.println(" <harmony_root> is the android client directory that contains working_classlib.");
+ System.out.println(" This should hold an up-to-date checkout of Harmony.");
+ System.out.println();
+ System.out.println(" <module> is one of " + Module.VALUES.keySet());
+ System.out.println();
+ System.out.println("Example usage:");
+ System.out.println(" java -cp out/host/linux-x86/framework/integrate.jar PushAndroidCode \\");
+ System.out.println(" /usr/local/google/jesse/clients/jessewilson_g1 \\");
+ System.out.println(" /usr/local/google/jesse/clients/jessewilson_h0/trunk \\");
+ System.out.println(" crypto");
+ }
+}
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLInputStream.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLInputStream.java
index 6c23a91..507e14f 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLInputStream.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLInputStream.java
@@ -94,10 +94,11 @@
* Reads and returns uint64 value.
*/
public long readUint64() throws IOException {
- return (read() << 56) | (read() << 48)
- | (read() << 40) | (read() << 32)
- | (read() << 24) | (read() << 16)
- | (read() << 8) | (read() & 0x00FF);
+ // BEGIN android-changed
+ long hi = readUint32();
+ long lo = readUint32();
+ return (hi << 32) | lo;
+ // END android-changed
}
/**
@@ -131,4 +132,3 @@
return i;
}
}
-
diff --git a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl.cpp b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl.cpp
index 13a1e61..eec2efe 100644
--- a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl.cpp
+++ b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl.cpp
@@ -41,20 +41,10 @@
static jfieldID field_ssl_ctx;
/**
- * Throws java.io.IOexception with the provided message.
+ * Throws java.io.IOException with the provided message.
*/
-static void throwIOExceptionStr(JNIEnv* env, const char* message)
-{
- jclass exClass = env->FindClass("java/io/IOException");
-
- if (exClass == NULL)
- {
- LOGE("Unable to find class java/io/IOException");
- }
- else
- {
- env->ThrowNew(exClass, message);
- }
+static void throwIOExceptionStr(JNIEnv* env, const char* message) {
+ jniThrowException(env, "java/io/IOException", message);
}
/**
@@ -87,9 +77,9 @@
// 'seed == null' when no SecureRandom Object is set
// in the SSLContext.
if (seed != NULL) {
- jboolean iscopy = JNI_FALSE;
- jbyte* randseed = env->GetByteArrayElements(seed, &iscopy);
+ jbyte* randseed = env->GetByteArrayElements(seed, NULL);
RAND_seed((unsigned char*) randseed, 1024);
+ env->ReleaseByteArrayElements(seed, randseed, 0);
} else {
RAND_load_file("/dev/urandom", 1024);
}
@@ -167,38 +157,13 @@
static jobjectArray org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl_getsupportedciphersuites(JNIEnv* env,
jobject object)
{
- SSL_CTX* ctx;
- SSL* ssl;
- STACK_OF(SSL_CIPHER) *sk;
- jobjectArray ret;
- int i;
- const char *c;
-
- ctx = SSL_CTX_new(SSLv23_server_method());
- ssl = SSL_new(ctx);
- sk=SSL_get_ciphers(ssl);
-
- ret= (jobjectArray)env->NewObjectArray(5,
- env->FindClass("java/lang/String"),
- env->NewStringUTF(""));
-
- i = 0;
- while (SSL_get_cipher_list(ssl,i) != NULL) {
- i++;
+ SSL_CTX* ssl_ctx = SSL_CTX_new(SSLv23_server_method());
+ if (ssl_ctx == NULL) {
+ return NULL;
}
-
- ret = (jobjectArray)env->NewObjectArray(i,
- env->FindClass("java/lang/String"),
- env->NewStringUTF(""));
-
- for (i=0; ; i++) {
- c=SSL_get_cipher_list(ssl,i);
- if (c == NULL) break;
-
- env->SetObjectArrayElement(ret,i,env->NewStringUTF(c));
- }
-
- return ret;
+ jobjectArray result = makeCipherList(env, ssl_ctx);
+ SSL_CTX_free(ssl_ctx);
+ return result;
}
/**
@@ -208,52 +173,20 @@
static jobjectArray org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl_getenabledciphersuites(JNIEnv* env,
jobject object)
{
- SSL_CTX* ctx;
- SSL* ssl;
- jobjectArray ret;
- int i;
- const char *c;
-
- ctx = (SSL_CTX*)env->GetIntField(object, field_ssl_ctx);
- ssl = SSL_new(ctx);
-
- i = 0;
- while (SSL_get_cipher_list(ssl,i) != NULL) {
- i++;
- }
-
- ret = (jobjectArray)env->NewObjectArray(i,
- env->FindClass("java/lang/String"),
- env->NewStringUTF(""));
-
- for (i = 0; ; i++) {
- c = SSL_get_cipher_list(ssl,i);
- if (c == NULL) break;
-
- env->SetObjectArrayElement(ret,i,env->NewStringUTF(c));
- }
-
- return ret;
+ SSL_CTX* ssl_ctx =
+ reinterpret_cast<SSL_CTX*>(env->GetIntField(object, field_ssl_ctx));
+ return makeCipherList(env, ssl_ctx);
}
/**
* Sets the ciphers suites that are enabled in the OpenSSL server.
*/
static void org_apache_harmony_xnet_provider_jsse_OpenSSLServerSocketImpl_setenabledciphersuites(JNIEnv* env,
- jobject object, jstring controlstring)
+ jobject object, jstring controlString)
{
- SSL_CTX* ctx;
- const char *str;
- int ret;
-
- ctx = (SSL_CTX*)env->GetIntField(object, field_ssl_ctx);
- str = env->GetStringUTFChars(controlstring, 0);
- ret = SSL_CTX_set_cipher_list(ctx, str);
-
- if(ret == 0) {
- jclass exClass = env->FindClass("java/lang/IllegalArgumentException");
- env->ThrowNew(exClass, "Illegal cipher suite strings.");
- }
+ SSL_CTX* ssl_ctx =
+ reinterpret_cast<SSL_CTX*>(env->GetIntField(object, field_ssl_ctx));
+ setEnabledCipherSuites(env, controlString, ssl_ctx);
}
/**
diff --git a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl.cpp b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl.cpp
index feae690..324dacf 100644
--- a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl.cpp
+++ b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl.cpp
@@ -47,20 +47,6 @@
}
/**
- * Throws java.io.IOexception with the provided message.
- */
-static void throwIOExceptionStr(JNIEnv* env, const char* message)
-{
- jclass exClass = env->FindClass("java/io/IOException");
-
- if (exClass == NULL) {
- LOGE("Unable to find class java/io/IOException");
- } else {
- env->ThrowNew(exClass, message);
- }
-}
-
-/**
* Gets the peer certificate in the chain and fills a byte array with the
* information therein.
*/
@@ -150,20 +136,15 @@
*/
static jbyteArray org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl_getid(JNIEnv* env, jobject object)
{
- SSL_SESSION * ssl_session;
- jbyteArray bytes;
- jbyte *tmp;
+ SSL_SESSION* ssl_session = getSslSessionPointer(env, object);
- ssl_session = getSslSessionPointer(env, object);
-
- bytes = env->NewByteArray(ssl_session->session_id_length);
- if (bytes != NULL) {
- tmp = env->GetByteArrayElements(bytes, NULL);
- memcpy(tmp, ssl_session->session_id, ssl_session->session_id_length);
- env->ReleaseByteArrayElements(bytes, tmp, 0);
+ jbyteArray result = env->NewByteArray(ssl_session->session_id_length);
+ if (result != NULL) {
+ jbyte* src = reinterpret_cast<jbyte*>(ssl_session->session_id);
+ env->SetByteArrayRegion(result, 0, ssl_session->session_id_length, src);
}
- return bytes;
+ return result;
}
/**
diff --git a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp
index 87f2af3..b474905 100644
--- a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp
+++ b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp
@@ -989,9 +989,9 @@
// 'seed == null' when no SecureRandom Object is set
// in the SSLContext.
if (seed != NULL) {
- jboolean iscopy = JNI_FALSE;
- jbyte* randseed = env->GetByteArrayElements(seed, &iscopy);
+ jbyte* randseed = env->GetByteArrayElements(seed, NULL);
RAND_seed((unsigned char*) randseed, 1024);
+ env->ReleaseByteArrayElements(seed, randseed, 0);
} else {
RAND_load_file("/dev/urandom", 1024);
}
@@ -1011,6 +1011,19 @@
*/
SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, NULL);
+ int mode = SSL_CTX_get_mode(ssl_ctx);
+ /*
+ * Turn on "partial write" mode. This means that SSL_write() will
+ * behave like Posix write() and possibly return after only
+ * writing a partial buffer. Note: The alternative, perhaps
+ * surprisingly, is not that SSL_write() always does full writes
+ * but that it will force you to retry write calls having
+ * preserved the full state of the original call. (This is icky
+ * and undesirable.)
+ */
+ mode |= SSL_MODE_ENABLE_PARTIAL_WRITE;
+ SSL_CTX_set_mode(ssl_ctx, mode);
+
if (privatekey != NULL) {
BIO* privatekeybio = stringToMemBuf(env, (jstring) privatekey);
EVP_PKEY* privatekeyevp =
@@ -1114,17 +1127,6 @@
fd = jniGetFDFromFileDescriptor(env, fdObject);
- /*
- * Turn on "partial write" mode. This means that SSL_write() will
- * behave like Posix write() and possibly return after only
- * writing a partial buffer. Note: The alternative, perhaps
- * surprisingly, is not that SSL_write() always does full writes
- * but that it will force you to retry write calls having
- * preserved the full state of the original call. (This is icky
- * and undesirable.)
- */
- SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
-
ssl_session = (SSL_SESSION *) session;
ret = SSL_set_fd(ssl, fd);
@@ -1404,45 +1406,13 @@
static jobjectArray org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl_getsupportedciphersuites(JNIEnv* env,
jobject object)
{
- SSL_CTX* ssl_ctx;
- SSL* ssl;
- jobjectArray ret;
- int i;
- const char *c;
-
- ssl_ctx = SSL_CTX_new(SSLv23_client_method());
-
+ SSL_CTX* ssl_ctx = SSL_CTX_new(SSLv23_client_method());
if (ssl_ctx == NULL) {
return NULL;
}
-
- ssl = SSL_new(ssl_ctx);
-
- if (ssl == NULL) {
- SSL_CTX_free(ssl_ctx);
- return NULL;
- }
-
- i = 0;
- while (SSL_get_cipher_list(ssl,i) != NULL) {
- i++;
- }
-
- ret = (jobjectArray)env->NewObjectArray(i,
- env->FindClass("java/lang/String"),
- env->NewStringUTF(""));
-
- for (i=0; ; i++) {
- c=SSL_get_cipher_list(ssl,i);
- if (c == NULL) break;
-
- env->SetObjectArrayElement(ret,i,env->NewStringUTF(c));
- }
-
- SSL_free(ssl);
+ jobjectArray result = makeCipherList(env, ssl_ctx);
SSL_CTX_free(ssl_ctx);
-
- return ret;
+ return result;
}
/**
@@ -1452,57 +1422,66 @@
static jobjectArray org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl_getenabledciphersuites(JNIEnv* env,
jobject object)
{
- SSL_CTX* ssl_ctx;
- SSL* ssl;
- jobjectArray ret;
- int i;
- const char *c;
-
- ssl = getSslPointer(env, object, false);
- if (ssl == NULL) {
- ssl_ctx = (SSL_CTX*)env->GetIntField(object, field_ssl_ctx);
- ssl = SSL_new(ssl_ctx);
- env->SetIntField(object, field_ssl, (int)ssl);
- }
-
- i = 0;
- while (SSL_get_cipher_list(ssl,i) != NULL) {
- i++;
- }
-
- ret = (jobjectArray)env->NewObjectArray(i,
- env->FindClass("java/lang/String"),
- env->NewStringUTF(""));
-
- for (i = 0; ; i++) {
- c = SSL_get_cipher_list(ssl,i);
- if (c == NULL) break;
-
- env->SetObjectArrayElement(ret,i,env->NewStringUTF(c));
- }
-
- return ret;
+ SSL_CTX* ssl_ctx =
+ reinterpret_cast<SSL_CTX*>(env->GetIntField(object, field_ssl_ctx));
+ return makeCipherList(env, ssl_ctx);
}
/**
* Sets the ciphers suites that are enabled in the OpenSSL client.
*/
static void org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl_setenabledciphersuites(JNIEnv* env, jobject object,
- jstring controlstring)
+ jstring controlString)
{
- SSL_CTX* ctx;
- const char *str;
- int ret;
+ SSL_CTX* ssl_ctx =
+ reinterpret_cast<SSL_CTX*>(env->GetIntField(object, field_ssl_ctx));
+ setEnabledCipherSuites(env, controlString, ssl_ctx);
+}
- ctx = (SSL_CTX*)env->GetIntField(object, field_ssl_ctx);
- str = env->GetStringUTFChars(controlstring, 0);
- ret = SSL_CTX_set_cipher_list(ctx, str);
+static jobjectArray makeCipherList(JNIEnv* env, SSL* ssl) {
+ // Count the ciphers.
+ int cipherCount = 0;
+ while (SSL_get_cipher_list(ssl, cipherCount) != NULL) {
+ ++cipherCount;
+ }
- if (ret == 0) {
+ // Create a String[].
+ jclass stringClass = env->FindClass("java/lang/String");
+ if (stringClass == NULL) {
+ return NULL;
+ }
+ jobjectArray array = env->NewObjectArray(cipherCount, stringClass, NULL);
+ if (array == NULL) {
+ return NULL;
+ }
+
+ // Fill in the cipher names.
+ for (int i = 0; i < cipherCount; ++i) {
+ const char* c = SSL_get_cipher_list(ssl, i);
+ env->SetObjectArrayElement(array, i, env->NewStringUTF(c));
+ }
+ return array;
+}
+
+jobjectArray makeCipherList(JNIEnv* env, SSL_CTX* ssl_ctx) {
+ SSL* ssl = SSL_new(ssl_ctx);
+ if (ssl == NULL) {
+ return NULL;
+ }
+ jobjectArray result = makeCipherList(env, ssl);
+ SSL_free(ssl);
+ return result;
+}
+
+void setEnabledCipherSuites(JNIEnv* env, jstring controlString, SSL_CTX* ssl_ctx) {
+ const char* str = env->GetStringUTFChars(controlString, NULL);
+ int rc = SSL_CTX_set_cipher_list(ssl_ctx, str);
+ env->ReleaseStringUTFChars(controlString, str);
+ if (rc == 0) {
freeSslErrorState();
- jclass exClass = env->FindClass("java/lang/IllegalArgumentException");
- env->ThrowNew(exClass, "Illegal cipher suite strings.");
- }
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ "Illegal cipher suite strings.");
+ }
}
#define SSL_AUTH_MASK 0x00007F00L
diff --git a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_common.h b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_common.h
index 9ed75be..e78cdd8 100644
--- a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_common.h
+++ b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_common.h
@@ -26,10 +26,10 @@
/**
* Structure to hold together useful JNI variables.
*/
-typedef struct {
+struct mydata_t {
JNIEnv* env;
jobject object;
-} mydata_t;
+};
/**
* Gives an array back containing all the X509 certificate's bytes.
@@ -76,9 +76,8 @@
joa = NULL;
break;
} else {
- jbyte *tmp = env->GetByteArrayElements(bytes, NULL);
- memcpy(tmp, bptr->data, bptr->length);
- env->ReleaseByteArrayElements(bytes, tmp, 0);
+ jbyte* src = reinterpret_cast<jbyte*>(bptr->data);
+ env->SetByteArrayRegion(bytes, 0, bptr->length, src);
env->SetObjectArrayElement(joa, i, bytes);
}
}
@@ -118,4 +117,7 @@
return 1;
}
+extern jobjectArray makeCipherList(JNIEnv* env, SSL_CTX* ssl);
+extern void setEnabledCipherSuites(JNIEnv* env, jstring controlString, SSL_CTX* ssl_ctx);
+
#endif
diff --git a/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLServerSocketTest.java b/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLServerSocketTest.java
index 3c1fb2e..c4bae0a 100644
--- a/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLServerSocketTest.java
+++ b/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLServerSocketTest.java
@@ -32,6 +32,7 @@
import java.io.InputStream;
import java.net.InetAddress;
import java.security.KeyStore;
+import java.security.SecureRandom;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
@@ -585,4 +586,26 @@
.createServerSocket();
return sss;
}
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Guard against native resource leakage.",
+ method = "SSLSocket",
+ args = {}
+ )
+ public void test_creationStressTest() throws Exception {
+ KeyManager[] keyManagers = getKeyManagers();
+ // Test the default codepath, which uses /dev/urandom.
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+ sslContext.init(keyManagers, null, null);
+ for (int i = 0; i < 2048; ++i) {
+ sslContext.getServerSocketFactory().createServerSocket();
+ }
+
+ // Test the other codepath, which copies a seed from a byte[].
+ sslContext.init(keyManagers, null, new SecureRandom());
+ for (int i = 0; i < 2048; ++i) {
+ sslContext.getServerSocketFactory().createServerSocket();
+ }
+ }
}
diff --git a/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLSocketTest.java b/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLSocketTest.java
index 5e39cb1..13a0e59 100644
--- a/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLSocketTest.java
+++ b/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLSocketTest.java
@@ -26,6 +26,7 @@
import java.net.*;
import java.security.KeyStore;
+import java.security.SecureRandom;
import java.lang.String;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -336,6 +337,27 @@
}
}
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Guard against native resource leakage.",
+ method = "SSLSocket",
+ args = {}
+ )
+ public void test_creationStressTest() throws Exception {
+ // Test the default codepath, which uses /dev/urandom.
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+ sslContext.init(null, null, null);
+ for (int i = 0; i < 2048; ++i) {
+ sslContext.getSocketFactory().createSocket();
+ }
+
+ // Test the other codepath, which copies a seed from a byte[].
+ sslContext.init(null, null, new SecureRandom());
+ for (int i = 0; i < 2048; ++i) {
+ sslContext.getSocketFactory().createSocket();
+ }
+ }
+
/**
* @throws IOException
* @tests javax.net.ssl.SSLSocket#addHandshakeCompletedListener(HandshakeCompletedListener listener)
diff --git a/libcore/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java b/libcore/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java
index f71d289..2fd16d0 100644
--- a/libcore/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java
+++ b/libcore/xml/src/main/java/org/apache/harmony/xml/dom/InnerNodeImpl.java
@@ -69,7 +69,7 @@
}
public Node getNextSibling() {
- if (parent == null || index >= parent.children.size()) {
+ if (parent == null || index + 1 >= parent.children.size()) {
return null;
}
diff --git a/libcore/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp b/libcore/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
index 40a4116..9192b1a 100644
--- a/libcore/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
+++ b/libcore/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
@@ -105,16 +105,7 @@
static jstring emptyString;
/**
- * Throws a NullPointerException.
- *
- * @param msg exception message
- */
-static void throw_NullPointerException(JNIEnv* env, const char* msg) {
- jniThrowException(env, "java/lang/NullPointerException", msg);
-}
-
-/**
- * Throw a NullPointerException.
+ * Throws OutOfMemoryError.
*/
static void throw_OutOfMemoryError(JNIEnv* env) {
jniThrowException(env, "java/lang/OutOfMemoryError", "Out of memory.");
@@ -336,15 +327,9 @@
return internString(env, parsingContext, nullTerminated);
}
-/**
- * Throw an assertion error.
- *
- * @param message to show
- */
-static void fail(JNIEnv* env, const char* message) {
- jclass clazz;
- clazz = env->FindClass("java/lang/AssertionError");
- env->ThrowNew(clazz, message);
+static void jniThrowExpatException(JNIEnv* env, XML_Error error) {
+ const char* message = XML_ErrorString(error);
+ jniThrowException(env, "org/apache/harmony/xml/ExpatException", message);
}
/**
@@ -805,18 +790,7 @@
env->CallVoidMethod(javaParser, processingInstructionMethod, javaTarget,
javaInstructionData);
- // We have to temporarily clear an exception before we can release local
- // references.
- jthrowable exception = env->ExceptionOccurred();
- if (exception != NULL) {
- env->ExceptionClear();
- }
-
env->DeleteLocalRef(javaInstructionData);
-
- if (exception != NULL) {
- env->Throw(exception);
- }
}
/**
@@ -1010,21 +984,10 @@
if (!XML_Parse(parser, (char*) characters, length, isFinal)
&& !env->ExceptionCheck()) {
- jclass clazz = env->FindClass("org/apache/harmony/xml/ExpatException");
- const char* errorMessage = XML_ErrorString(XML_GetErrorCode(parser));
- env->ThrowNew(clazz, errorMessage);
+ jniThrowExpatException(env, XML_GetErrorCode(parser));
}
- // We have to temporarily clear an exception before we can release local
- // references.
- jthrowable exception = env->ExceptionOccurred();
- if (exception) {
- env->ExceptionClear();
- env->ReleaseStringChars(xml, characters);
- env->Throw(exception);
- } else {
- env->ReleaseStringChars(xml, characters);
- }
+ env->ReleaseStringChars(xml, characters);
context->object = NULL;
context->env = NULL;
@@ -1050,21 +1013,10 @@
if (!XML_Parse(parser, ((char*) characters) + (offset << 1),
length << 1, XML_FALSE) && !env->ExceptionCheck()) {
- jclass clazz = env->FindClass("org/apache/harmony/xml/ExpatException");
- const char* errorMessage = XML_ErrorString(XML_GetErrorCode(parser));
- env->ThrowNew(clazz, errorMessage);
+ jniThrowExpatException(env, XML_GetErrorCode(parser));
}
- // We have to temporarily clear an exception before we can release local
- // references.
- jthrowable exception = env->ExceptionOccurred();
- if (exception) {
- env->ExceptionClear();
- env->ReleaseCharArrayElements(xml, characters, JNI_ABORT);
- env->Throw(exception);
- } else {
- env->ReleaseCharArrayElements(xml, characters, JNI_ABORT);
- }
+ env->ReleaseCharArrayElements(xml, characters, JNI_ABORT);
context->object = NULL;
context->env = NULL;
@@ -1090,21 +1042,10 @@
if (!XML_Parse(parser, ((char*) bytes) + offset, length, XML_FALSE)
&& !env->ExceptionCheck()) {
- jclass clazz = env->FindClass("org/apache/harmony/xml/ExpatException");
- const char* errorMessage = XML_ErrorString(XML_GetErrorCode(parser));
- env->ThrowNew(clazz, errorMessage);
+ jniThrowExpatException(env, XML_GetErrorCode(parser));
}
- // We have to temporarily clear an exception before we can release local
- // references.
- jthrowable exception = env->ExceptionOccurred();
- if (exception) {
- env->ExceptionClear();
- env->ReleaseByteArrayElements(xml, bytes, JNI_ABORT);
- env->Throw(exception);
- } else {
- env->ReleaseByteArrayElements(xml, bytes, JNI_ABORT);
- }
+ env->ReleaseByteArrayElements(xml, bytes, JNI_ABORT);
context->object = NULL;
context->env = NULL;
@@ -1308,26 +1249,21 @@
return getAttributeIndexForQName(
env, clazz, attributePointer, localName);
}
-
int localNameLength = env->GetStringUTFLength(localName);
// Create string in the same format used by Expat: "uri|localName"
+ // TODO: do we have a guarantee that uriLength and localNameLength are small?
char concatenated[uriLength + localNameLength + 2];
// Append uri.
- const char* uriBytes = env->GetStringUTFChars(uri, NULL);
- if (uriBytes == NULL) return -1;
- strcpy(concatenated, uriBytes);
- env->ReleaseStringUTFChars(uri, uriBytes);
+ env->GetStringUTFRegion(uri, 0, uriLength, concatenated);
- // Separarator.
+ // Separator.
concatenated[uriLength] = '|';
// Append local name.
- const char* localNameBytes = env->GetStringUTFChars(localName, NULL);
- if (localNameBytes == NULL) return -1;
- strcpy(concatenated + uriLength + 1, localNameBytes);
- env->ReleaseStringUTFChars(localName, localNameBytes);
+ env->GetStringUTFRegion(localName, 0, localNameLength,
+ concatenated + uriLength + 1);
return findAttributeByName(attributes, concatenated);
}
diff --git a/libcore/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTestSupport.java b/libcore/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTestSupport.java
index bc5e6a1..a1627ba 100644
--- a/libcore/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTestSupport.java
+++ b/libcore/xml/src/test/java/tests/api/javax/xml/parsers/SAXParserTestSupport.java
@@ -54,7 +54,7 @@
public static final String KEY_ERROR = "error";
public static final String KEY_FATAL_ERROR = "fatalError";
public static final String KEY_WARNING = "warning";
- public static final String KEY_END_ELEMENT = "endEement";
+ public static final String KEY_END_ELEMENT = "endElement";
public static final String KEY_END_PREFIX_MAPPING = "endPrefixMapping";
public static final String KEY_IGNORABLE_WHITE_SPACE =
"ignorableWhitespace";
diff --git a/libcore/xml/src/test/java/tests/xml/AllTests.java b/libcore/xml/src/test/java/tests/xml/AllTests.java
index eefae50..8c089e3 100644
--- a/libcore/xml/src/test/java/tests/xml/AllTests.java
+++ b/libcore/xml/src/test/java/tests/xml/AllTests.java
@@ -26,6 +26,7 @@
suite.addTestSuite(SimpleParserTest.class);
suite.addTestSuite(SimpleBuilderTest.class);
+ suite.addTestSuite(NodeTests.class);
//suite.addTest(tests.org.w3c.dom.AllTests.suite());
suite.addTest(tests.api.javax.xml.parsers.AllTests.suite());
diff --git a/libcore/xml/src/test/java/tests/xml/NodeTests.java b/libcore/xml/src/test/java/tests/xml/NodeTests.java
new file mode 100644
index 0000000..e46e216
--- /dev/null
+++ b/libcore/xml/src/test/java/tests/xml/NodeTests.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+package tests.xml;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import junit.framework.TestCase;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import java.io.ByteArrayInputStream;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+@TestTargetClass(Node.class)
+public class NodeTests extends TestCase {
+ @TestTargetNew(
+ level = TestLevel.PARTIAL,
+ notes = "Issue #779: org.w3c.dom.Node#getNextSibling throws IndexOutOfBoundsException.",
+ method = "getNextSibling",
+ args = {}
+ )
+ public void test_getNextSibling() throws Exception {
+ // Calling getNextSibling when there is no next sibling should return null.
+ // From http://code.google.com/p/android/issues/detail?id=779.
+ ByteArrayInputStream bis = new ByteArrayInputStream("<root/>".getBytes());
+ Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(bis);
+ Node root = document.getDocumentElement();
+ assertNull(root.getNextSibling());
+ }
+}
diff --git a/libnativehelper/Android.mk b/libnativehelper/Android.mk
index aa4be86..f030fea 100644
--- a/libnativehelper/Android.mk
+++ b/libnativehelper/Android.mk
@@ -55,8 +55,8 @@
LOCAL_SRC_FILES := $(src_files)
LOCAL_C_INCLUDES := $(c_includes)
-LOCAL_SHARED_LIBRARIES := $(shared_libraries)
LOCAL_STATIC_LIBRARIES := $(static_libraries)
+LOCAL_SHARED_LIBRARIES := $(shared_libraries)
# liblog and libcutils are shared for target.
LOCAL_SHARED_LIBRARIES += \
@@ -77,15 +77,23 @@
LOCAL_SRC_FILES := $(src_files)
LOCAL_C_INCLUDES := $(c_includes)
- LOCAL_SHARED_LIBRARIES := $(shared_libraries)
LOCAL_STATIC_LIBRARIES := $(static_libraries)
+ ifeq ($(HOST_OS)-$(HOST_ARCH),darwin-x86)
+ # OSX has a lot of libraries built in, which we don't have to
+ # bother building; just include them on the ld line.
+ LOCAL_LDLIBS := -lexpat -lssl -lz -lcrypto -licucore -lsqlite3
+ LOCAL_STATIC_LIBRARIES += libutils
+ else
+ LOCAL_SHARED_LIBRARIES := $(shared_libraries)
+ endif
+
# liblog and libcutils are static for host.
LOCAL_STATIC_LIBRARIES += \
liblog libcutils
LOCAL_MODULE := libnativehelper-host
- include $(BUILD_HOST_SHARED_LIBRARY)
+ include $(BUILD_HOST_STATIC_LIBRARY)
endif
diff --git a/tests/020-string/expected.txt b/tests/020-string/expected.txt
index 67b7159..081fea3 100644
--- a/tests/020-string/expected.txt
+++ b/tests/020-string/expected.txt
@@ -3,3 +3,5 @@
Compare result is 32
Compare unicode: -65302
Got expected exception
+subStr is 'uick brown fox jumps over the lazy '
+Indexes are: 0:-1:0:43:33:-1:18:13:13:-1:18:18:-1:13:-1:-1:-1
diff --git a/tests/020-string/src/Main.java b/tests/020-string/src/Main.java
index 4a57fc6..bb8ce1f 100644
--- a/tests/020-string/src/Main.java
+++ b/tests/020-string/src/Main.java
@@ -19,6 +19,11 @@
*/
public class Main {
public static void main(String args[]) {
+ basicTest();
+ indexTest();
+ }
+
+ public static void basicTest() {
String baseStr = "*** This is a very nice string!!!";
String testStr;
int i;
@@ -49,4 +54,31 @@
System.out.println("Got expected exception");
}
}
+
+ public static void indexTest() {
+ String baseStr = "The quick brown fox jumps over the lazy dog!";
+ String subStr;
+
+ subStr = baseStr.substring(5, baseStr.length() - 4);
+ System.out.println("subStr is '" + subStr + "'");
+
+ System.out.println("Indexes are: " +
+ baseStr.indexOf('T') + ":" +
+ subStr.indexOf('T') + ":" +
+ subStr.indexOf('u') + ":" +
+ baseStr.indexOf('!') + ":" +
+ subStr.indexOf('y') + ":" +
+ subStr.indexOf('d') + ":" +
+ baseStr.indexOf('x') + ":" +
+ subStr.indexOf('x', 0) + ":" +
+ subStr.indexOf('x', -1) + ":" +
+ subStr.indexOf('x', 200) + ":" +
+ baseStr.indexOf('x', 17) + ":" +
+ baseStr.indexOf('x', 18) + ":" +
+ baseStr.indexOf('x', 19) + ":" +
+ subStr.indexOf('x', 13) + ":" +
+ subStr.indexOf('x', 14) + ":" +
+ subStr.indexOf('&') + ":" +
+ baseStr.indexOf(0x12341234));
+ }
}
diff --git a/tests/062-character-encodings/expected.txt b/tests/062-character-encodings/expected.txt
index e82e437..aa0279a 100644
--- a/tests/062-character-encodings/expected.txt
+++ b/tests/062-character-encodings/expected.txt
@@ -22,19 +22,29 @@
ibm-954
ibm-954_P101-2007
ujis
-GB2312
- 1383
- EUC-CN
- cp1383
- csGB2312
- hp15CN
- ibm-1383
- ibm-1383_P110-1999
- ibm-1383_VPUA
- ibm-eucCN
+EUC-KR
+ 5601
+ KSC_5601
+ KS_C_5601-1987
+ KS_C_5601-1989
+ csEUCKR
+ csKSC56011987
+ iso-ir-149
+ korean
+ ms949
+ windows-949
+ windows-949-2000
GBK
CP936
+ EUC-CN
+ GB2312
+ GB_2312-80
MS936
+ chinese
+ csGB2312
+ csISO58GB231280
+ gb2312-1980
+ iso-ir-58
windows-936
windows-936-2000
HZ-GB-2312
@@ -223,12 +233,14 @@
x-ms-cp932
x-sjis
TIS-620
+ MS874
cp874
eucTH
ibm-874
- ibm-874_P100-1995
ibm-9066
tis620.2533
+ windows-874
+ windows-874-2000
US-ASCII
646
ANSI_X3.4-1968
@@ -351,16 +363,14 @@
x-gsm-03.38-2000
GSM0338
gsm-03.38-2000
-x-ibm-1373_P100-2002
- ibm-1373
- ibm-1373_P100-2002
- windows-950
-x-ibm-1386_P100-2001
- cp1386
- ibm-1386
- ibm-1386_P100-2001
- ibm-1386_VSUB_VPUA
- windows-936
+x-ibm-1383_P110-1999
+ 1383
+ cp1383
+ hp15CN
+ ibm-1383
+ ibm-1383_P110-1999
+ ibm-1383_VPUA
+ ibm-eucCN
x-IMAP-mailbox-name
IMAP-mailbox-name
x-iscii-be
diff --git a/tests/079-phantom/expected.txt b/tests/079-phantom/expected.txt
new file mode 100644
index 0000000..a932b77
--- /dev/null
+++ b/tests/079-phantom/expected.txt
@@ -0,0 +1,14 @@
+start
+Created Bitmap one: 10x10 (100)
+Created Bitmap two: 20x20 (101)
+Created Bitmap three/four: 20x20 (101)
+Drawing Bitmap two: 20x20 (101)
+nulling 1
+freeNativeStorage: 100
+nulling 2
+nulling 3
+nulling 4
+freeNativeStorage: 101
+intr
+Bitmap has shut down
+done
diff --git a/tests/079-phantom/info.txt b/tests/079-phantom/info.txt
new file mode 100644
index 0000000..d974e2c
--- /dev/null
+++ b/tests/079-phantom/info.txt
@@ -0,0 +1 @@
+Exercise phantom references.
diff --git a/tests/079-phantom/src/Bitmap.java b/tests/079-phantom/src/Bitmap.java
new file mode 100644
index 0000000..4d9c259
--- /dev/null
+++ b/tests/079-phantom/src/Bitmap.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.PhantomReference;
+import java.util.ArrayList;
+
+public class Bitmap {
+ String mName; /* for debugging */
+ int mWidth, mHeight;
+ Bitmap.NativeWrapper mNativeWrapper;
+
+ private static int sSerial = 100;
+ private static ArrayList sPhantomList = new ArrayList<PhantomWrapper>();
+ private static ReferenceQueue<PhantomWrapper> sPhantomQueue =
+ new ReferenceQueue<PhantomWrapper>();
+ private static BitmapWatcher sWatcher = new BitmapWatcher(sPhantomQueue);
+ static {
+ sWatcher.start();
+ };
+
+ Bitmap(String name, int width, int height, Bitmap.NativeWrapper nativeData) {
+ mName = name;
+ mWidth = width;
+ mHeight = height;
+ mNativeWrapper = nativeData;
+
+ System.out.println("Created " + this);
+ }
+
+ public String toString() {
+ return "Bitmap " + mName + ": " + mWidth + "x" + mHeight + " (" +
+ mNativeWrapper.mNativeData + ")";
+ }
+
+ public void drawAt(int x, int y) {
+ System.out.println("Drawing " + this);
+ }
+
+ public static void shutDown() {
+ sWatcher.shutDown();
+ try {
+ sWatcher.join();
+ } catch (InterruptedException ie) {
+ System.out.println("join intr");
+ }
+ System.out.println("Bitmap has shut down");
+ }
+
+ /*
+ * Pretend we're allocating native storage. Just returns a unique
+ * serial number.
+ */
+ static Bitmap.NativeWrapper allocNativeStorage(int width, int height) {
+ int nativeData;
+
+ synchronized (Bitmap.class) {
+ nativeData = sSerial++;
+ }
+
+ Bitmap.NativeWrapper wrapper = new Bitmap.NativeWrapper(nativeData);
+ PhantomWrapper phan = new PhantomWrapper(wrapper, sPhantomQueue,
+ nativeData);
+ sPhantomList.add(phan);
+ return wrapper;
+ }
+
+ static void freeNativeStorage(int nativeDataPtr) {
+ System.out.println("freeNativeStorage: " + nativeDataPtr);
+ }
+
+ /*
+ * Wraps a native data pointer in an object. When this object is no
+ * longer referenced, we free the native data.
+ */
+ static class NativeWrapper {
+ public NativeWrapper(int nativeDataPtr) {
+ mNativeData = nativeDataPtr;
+ }
+ public int mNativeData;
+
+ /*
+ @Override
+ protected void finalize() throws Throwable {
+ System.out.println("finalized " + mNativeData);
+ }
+ */
+ }
+}
+
+/*
+ * Keep an eye on the native data.
+ *
+ * We keep a copy of the native data pointer value, and set the wrapper
+ * as our referent. We need the copy because you can't get the referred-to
+ * object back out of a PhantomReference.
+ */
+class PhantomWrapper extends PhantomReference {
+ PhantomWrapper(Bitmap.NativeWrapper wrapper,
+ ReferenceQueue<PhantomWrapper> queue, int nativeDataPtr)
+ {
+ super(wrapper, queue);
+ mNativeData = nativeDataPtr;
+ }
+
+ public int mNativeData;
+}
+
+/*
+ * Thread that watches for un-referenced bitmap data.
+ */
+class BitmapWatcher extends Thread {
+ ReferenceQueue<PhantomWrapper> mQueue;
+ volatile boolean mQuit = false;
+
+ BitmapWatcher(ReferenceQueue<PhantomWrapper> queue) {
+ mQueue = queue;
+ setName("Bitmap Watcher");
+ }
+
+ public void run() {
+ while (!mQuit) {
+ try {
+ PhantomWrapper ref = (PhantomWrapper) mQueue.remove();
+ //System.out.println("dequeued ref " + ref.mNativeData +
+ // " - " + ref);
+ Bitmap.freeNativeStorage(ref.mNativeData);
+ //ref.clear();
+ } catch (InterruptedException ie) {
+ System.out.println("intr");
+ }
+ }
+ }
+
+ public void shutDown() {
+ mQuit = true;
+ interrupt();
+ }
+}
+
diff --git a/tests/079-phantom/src/Main.java b/tests/079-phantom/src/Main.java
new file mode 100644
index 0000000..3965481
--- /dev/null
+++ b/tests/079-phantom/src/Main.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+public class Main {
+ Bitmap mBitmap1, mBitmap2, mBitmap3, mBitmap4;
+
+ public static void sleep(int ms) {
+ try {
+ Thread.sleep(ms);
+ } catch (InterruptedException ie) {
+ System.err.println("sleep interrupted");
+ }
+ }
+
+ public static void main(String args[]) {
+ System.out.println("start");
+
+ Main main = new Main();
+ main.run();
+
+ sleep(1000);
+ System.out.println("done");
+ }
+
+ public void run() {
+ createBitmaps();
+
+ System.gc();
+ sleep(250);
+
+ mBitmap2.drawAt(0, 0);
+
+ System.out.println("nulling 1");
+ mBitmap1 = null;
+ System.gc();
+ sleep(500);
+
+ System.out.println("nulling 2");
+ mBitmap2 = null;
+ System.gc();
+ sleep(500);
+
+ System.out.println("nulling 3");
+ mBitmap3 = null;
+ System.gc();
+ sleep(500);
+
+ System.out.println("nulling 4");
+ mBitmap4 = null;
+ System.gc();
+ sleep(500);
+
+ Bitmap.shutDown();
+ }
+
+ /*
+ * Create bitmaps.
+ *
+ * bitmap1 is 10x10 and unique
+ * bitmap2 and bitmap3 are 20x20 and share the same storage.
+ * bitmap4 is just another reference to bitmap3
+ *
+ * When we return there should be no local refs lurking on the stack.
+ */
+ public void createBitmaps() {
+ Bitmap.NativeWrapper dataA = Bitmap.allocNativeStorage(10, 10);
+ Bitmap.NativeWrapper dataB = Bitmap.allocNativeStorage(20, 20);
+ mBitmap1 = new Bitmap("one", 10, 10, dataA);
+ mBitmap2 = new Bitmap("two", 20, 20, dataB);
+ mBitmap3 = mBitmap4 = new Bitmap("three/four", 20, 20, dataB);
+ }
+}
+
diff --git a/tests/080-oom-throw/expected.txt b/tests/080-oom-throw/expected.txt
new file mode 100644
index 0000000..811f68c
--- /dev/null
+++ b/tests/080-oom-throw/expected.txt
@@ -0,0 +1,2 @@
+Array allocation failed
+Instance allocation failed
diff --git a/tests/080-oom-throw/info.txt b/tests/080-oom-throw/info.txt
new file mode 100644
index 0000000..e8ae6f6
--- /dev/null
+++ b/tests/080-oom-throw/info.txt
@@ -0,0 +1,3 @@
+Inject memory allocation failures for NEW_ARRAY and NEW_INSTANCE and make sure
+the JIT'ed code handles OOM exception correctly since it cannot fall back to
+the interpreter and re-execute the bytecode.
diff --git a/tests/080-oom-throw/src/Main.java b/tests/080-oom-throw/src/Main.java
new file mode 100644
index 0000000..3d75f3d
--- /dev/null
+++ b/tests/080-oom-throw/src/Main.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+public class Main {
+ static class ArrayMemEater {
+ static int blowup(char[][] holder, int size) {
+ int i = 0;
+ try {
+ for ( ; i < size; i++)
+ holder[i] = new char[128];
+ } catch (OutOfMemoryError oome) {
+ return i;
+ }
+
+ return size;
+ }
+
+ static void confuseCompilerOptimization(char[][] holder) {
+ }
+ }
+
+ static class InstanceMemEater {
+ InstanceMemEater next;
+ double d1, d2, d3, d4, d5, d6, d7, d8;
+
+ static InstanceMemEater blowup() {
+ InstanceMemEater memEater;
+ try {
+ memEater = new InstanceMemEater();
+ } catch (OutOfMemoryError e) {
+ memEater = null;
+ }
+ return memEater;
+ }
+
+ static void confuseCompilerOptimization(InstanceMemEater memEater) {
+ }
+ }
+
+ static void triggerArrayOOM() {
+ int size = 1 * 1024 * 1024;
+ char[][] holder = new char[size][];
+
+ int count = ArrayMemEater.blowup(holder, size);
+ ArrayMemEater.confuseCompilerOptimization(holder);
+ if (count < size) {
+ System.out.println("Array allocation failed");
+ }
+ }
+
+ static void triggerInstanceOOM() {
+ InstanceMemEater memEater = InstanceMemEater.blowup();
+ InstanceMemEater lastMemEater = memEater;
+ do {
+ lastMemEater.next = InstanceMemEater.blowup();
+ lastMemEater = lastMemEater.next;
+ } while (lastMemEater != null);
+ memEater.confuseCompilerOptimization(memEater);
+ System.out.println("Instance allocation failed");
+ }
+
+ public static void main(String[] args) {
+ triggerArrayOOM();
+ triggerInstanceOOM();
+ }
+}
diff --git a/tests/081-hot-exceptions/expected.txt b/tests/081-hot-exceptions/expected.txt
new file mode 100644
index 0000000..2432ff4
--- /dev/null
+++ b/tests/081-hot-exceptions/expected.txt
@@ -0,0 +1,2 @@
+sum = 0
+exception = 1024
diff --git a/tests/081-hot-exceptions/info.txt b/tests/081-hot-exceptions/info.txt
new file mode 100644
index 0000000..cc514f3
--- /dev/null
+++ b/tests/081-hot-exceptions/info.txt
@@ -0,0 +1,3 @@
+Make a hot exception-throwing path to stress test how the trace builder handles
+exceptions encountered during trace selection. The existence of exceptions will
+cause a control flow change to deviate from the current method.
diff --git a/tests/081-hot-exceptions/src/Main.java b/tests/081-hot-exceptions/src/Main.java
new file mode 100644
index 0000000..90e7af2
--- /dev/null
+++ b/tests/081-hot-exceptions/src/Main.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+public class Main {
+ static class ArrayObj {
+ int[] array;
+
+ int getArrayElement(int i) throws NullPointerException {
+ return array[i];
+ }
+ }
+
+ public static void main(String[] args) {
+ ArrayObj arrayObj2 = new ArrayObj();
+ int sum = 0;
+ int exception = 0;
+
+ for (int i = 0; i < 1024; i++) {
+ try {
+ // A hot method invocation that always encounters exceptions
+ sum += arrayObj2.getArrayElement(i);
+ } catch (NullPointerException npe) {
+ exception++;
+ }
+ }
+ System.out.println("sum = " + sum);
+ System.out.println("exception = " + exception);
+ }
+}
diff --git a/tools/dexcheck b/tools/dexcheck
index 76662e8..ff3e98d 100755
--- a/tools/dexcheck
+++ b/tools/dexcheck
@@ -1,5 +1,19 @@
#!/bin/bash
#
+# Copyright (C) 2009 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.
+
# This requires read permission on /data/dalvik-cache. On an eng build this
# works, on userdebug you will need to "adb root", or "su" followed by
# "chmod 777 /data/dalvik-cache".
@@ -14,7 +28,7 @@
failure=0
# Check each file in turn. This is much faster with "dexdump -c", but that
-# was added post-cupcake.
+# flag was not available in 1.6 and earlier.
#
# The dexdump found in older builds does not stop on checksum failures and
# will likely crash.
diff --git a/vm/Android.mk b/vm/Android.mk
index 5c276aa..6e71655 100644
--- a/vm/Android.mk
+++ b/vm/Android.mk
@@ -69,14 +69,21 @@
LOCAL_STATIC_LIBRARIES += \
liblog libcutils
- # libffi is called libffi-host on the host. Similarly libnativehelper.
- LOCAL_SHARED_LIBRARIES := \
- $(patsubst libffi,libffi-host,$(LOCAL_SHARED_LIBRARIES))
- LOCAL_SHARED_LIBRARIES := \
- $(patsubst libnativehelper,libnativehelper-host,$(LOCAL_SHARED_LIBRARIES))
+ # libffi is called libffi-host on the host and should be staticly
+ # linked. Similarly libnativehelper.
+ ifneq (,$(findstring libffi,$(LOCAL_SHARED_LIBRARIES)))
+ LOCAL_SHARED_LIBRARIES := \
+ $(patsubst libffi, ,$(LOCAL_SHARED_LIBRARIES))
+ LOCAL_STATIC_LIBRARIES += libffi-host
+ endif
+ ifneq (,$(findstring libnativehelper,$(LOCAL_SHARED_LIBRARIES)))
+ LOCAL_SHARED_LIBRARIES := \
+ $(patsubst libnativehelper, ,$(LOCAL_SHARED_LIBRARIES))
+ LOCAL_STATIC_LIBRARIES += libnativehelper-host
+ endif
LOCAL_MODULE := libdvm-host
- include $(BUILD_HOST_SHARED_LIBRARY)
+ include $(BUILD_HOST_STATIC_LIBRARY)
endif
diff --git a/vm/DalvikVersion.h b/vm/DalvikVersion.h
index efbb393..eae335d 100644
--- a/vm/DalvikVersion.h
+++ b/vm/DalvikVersion.h
@@ -24,7 +24,7 @@
* The version we show to tourists.
*/
#define DALVIK_MAJOR_VERSION 1
-#define DALVIK_MINOR_VERSION 1
+#define DALVIK_MINOR_VERSION 2
#define DALVIK_BUG_VERSION 0
/*
@@ -32,6 +32,6 @@
* 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 17
+#define DALVIK_VM_BUILD 18
#endif /*_DALVIK_VERSION*/
diff --git a/vm/Debugger.c b/vm/Debugger.c
index 4ddf25c..eec8176 100644
--- a/vm/Debugger.c
+++ b/vm/Debugger.c
@@ -419,7 +419,7 @@
dvmHashTableLock(gDvm.dbgRegistry);
gDvm.debuggerConnected = false;
- LOGI("Debugger has detached; object registry had %d entries\n",
+ LOGD("Debugger has detached; object registry had %d entries\n",
dvmHashTableNumEntries(gDvm.dbgRegistry));
//int i;
//for (i = 0; i < gDvm.dbgRegistryNext; i++)
@@ -512,6 +512,15 @@
}
/*
+ * Convert a RefTypeId to an ObjectId.
+ */
+ObjectId dvmDbgGetClassObject(RefTypeId id)
+{
+ ClassObject* clazz = refTypeIdToClassObject(id);
+ return objectToObjectId((Object*) clazz);
+}
+
+/*
* Return the superclass of a class (will be NULL for java/lang/Object).
*/
RefTypeId dvmDbgGetSuperclass(RefTypeId id)
@@ -1117,6 +1126,19 @@
}
/*
+ * Allocate a new object of the specified type.
+ *
+ * Add it to the registry to prevent it from being GCed.
+ */
+ObjectId dvmDbgCreateObject(RefTypeId classId)
+{
+ ClassObject* clazz = refTypeIdToClassObject(classId);
+ Object* newObj = dvmAllocObject(clazz, ALLOC_DEFAULT);
+ dvmReleaseTrackedAlloc(newObj, NULL);
+ return objectToObjectId(newObj);
+}
+
+/*
* Determine if "instClassId" is an instance of "classId".
*/
bool dvmDbgMatchType(RefTypeId instClassId, RefTypeId classId)
@@ -2676,6 +2698,30 @@
}
/*
+ * We currently have a bug where we don't successfully resume the
+ * target thread if the suspend count is too deep. We're expected to
+ * require one "resume" for each "suspend", but when asked to execute
+ * a method we have to resume fully and then re-suspend it back to the
+ * same level. (The easiest way to cause this is to type "suspend"
+ * multiple times in jdb.)
+ *
+ * It's unclear what this means when the event specifies "resume all"
+ * and some threads are suspended more deeply than others. This is
+ * a rare problem, so for now we just prevent it from hanging forever
+ * by rejecting the method invocation request. Without this, we will
+ * be stuck waiting on a suspended thread.
+ */
+ if (targetThread->suspendCount > 1) {
+ LOGW("threadid=%d: suspend count on threadid=%d is %d, too deep "
+ "for method exec\n",
+ dvmThreadSelf()->threadId, targetThread->threadId,
+ targetThread->suspendCount);
+ err = ERR_THREAD_SUSPENDED; /* probably not expected here */
+ dvmUnlockThreadList();
+ goto bail;
+ }
+
+ /*
* TODO: ought to screen the various IDs, and verify that the argument
* list is valid.
*/
@@ -2796,9 +2842,11 @@
/*
* Translate the method through the vtable, unless we're calling a
- * static method or the debugger wants to suppress it.
+ * direct method or the debugger wants to suppress it.
*/
- if ((pReq->options & INVOKE_NONVIRTUAL) != 0 || pReq->obj == NULL) {
+ if ((pReq->options & INVOKE_NONVIRTUAL) != 0 || pReq->obj == NULL ||
+ dvmIsDirectMethod(pReq->method))
+ {
meth = pReq->method;
} else {
meth = dvmGetVirtualizedMethod(pReq->clazz, pReq->method);
@@ -2809,8 +2857,8 @@
IF_LOGV() {
char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
- LOGV("JDWP invoking method %s.%s %s\n",
- meth->clazz->descriptor, meth->name, desc);
+ LOGV("JDWP invoking method %p/%p %s.%s:%s\n",
+ pReq->method, meth, meth->clazz->descriptor, meth->name, desc);
free(desc);
}
@@ -2819,8 +2867,10 @@
pReq->exceptObj = objectToObjectId(dvmGetException(self));
pReq->resultTag = resultTagFromSignature(meth);
if (pReq->exceptObj != 0) {
- LOGD(" JDWP invocation returning with exceptObj=%p\n",
- dvmGetException(self));
+ Object* exc = dvmGetException(self);
+ LOGD(" JDWP invocation returning with exceptObj=%p (%s)\n",
+ exc, exc->clazz->descriptor);
+ //dvmLogExceptionStackTrace();
dvmClearException(self);
/*
* Nothing should try to use this, but it looks like something is.
diff --git a/vm/Debugger.h b/vm/Debugger.h
index fcf07c7..189e2be 100644
--- a/vm/Debugger.h
+++ b/vm/Debugger.h
@@ -159,6 +159,7 @@
* Class, Object, Array
*/
const char* dvmDbgGetClassDescriptor(RefTypeId id);
+ObjectId dvmDbgGetClassObject(RefTypeId id);
RefTypeId dvmDbgGetSuperclass(RefTypeId id);
ObjectId dvmDbgGetClassLoader(RefTypeId id);
u4 dvmDbgGetAccessFlags(RefTypeId id);
@@ -188,6 +189,7 @@
const u1* buf);
ObjectId dvmDbgCreateString(const char* str);
+ObjectId dvmDbgCreateObject(RefTypeId classId);
bool dvmDbgMatchType(RefTypeId instClassId, RefTypeId classId);
diff --git a/vm/Dvm.mk b/vm/Dvm.mk
index 96f6dac..5aea242 100644
--- a/vm/Dvm.mk
+++ b/vm/Dvm.mk
@@ -194,23 +194,34 @@
test/TestHash.c \
test/TestIndirectRefTable.c
-ifeq ($(WITH_JIT_TUNING),true)
- LOCAL_CFLAGS += -DWITH_JIT_TUNING
- # NOTE: Turn on assertion for JIT for now
- LOCAL_CFLAGS += -UNDEBUG -DDEBUG=1 -DLOG_NDEBUG=1 -DWITH_DALVIK_ASSERT
-endif
+WITH_JIT := $(strip $(WITH_JIT))
ifeq ($(WITH_JIT),true)
LOCAL_CFLAGS += -DWITH_JIT
+ # Enable assert and JIT_TUNING for now
+ LOCAL_CFLAGS += -UNDEBUG -DDEBUG=1 -DLOG_NDEBUG=1 -DWITH_DALVIK_ASSERT
+ WITH_JIT_TUNING := true
LOCAL_SRC_FILES += \
../dexdump/OpCodeNames.c \
compiler/Compiler.c \
compiler/Frontend.c \
compiler/Utility.c \
compiler/IntermediateRep.c \
+ compiler/Dataflow.c \
+ compiler/Loop.c \
interp/Jit.c
endif
+ifeq ($(strip $(WITH_JIT_TUNING)),true)
+ LOCAL_CFLAGS += -DWITH_JIT_TUNING
+endif
+
+# Enable JIT self verification tool. Runs compiled traces natively, then replays
+# them with the interpreter, and ensures memory and register state are the same.
+ifeq ($(WITH_SELF_VERIFICATION),true)
+ LOCAL_CFLAGS += -DWITH_SELF_VERIFICATION
+endif
+
WITH_HPROF := $(strip $(WITH_HPROF))
ifeq ($(WITH_HPROF),)
WITH_HPROF := true
@@ -308,7 +319,13 @@
ifeq ($(MTERP_ARCH_KNOWN),false)
# unknown architecture, try to use FFI
LOCAL_C_INCLUDES += external/libffi/$(dvm_os)-$(dvm_arch)
- LOCAL_SHARED_LIBRARIES += libffi
+
+ ifeq ($(dvm_os)-$(dvm_arch),darwin-x86)
+ # OSX includes libffi, so just make the linker aware of it directly.
+ LOCAL_LDLIBS += -lffi
+ else
+ LOCAL_SHARED_LIBRARIES += libffi
+ endif
LOCAL_SRC_FILES += \
arch/generic/Call.c \
diff --git a/vm/Globals.h b/vm/Globals.h
index 9b12d84..23b7497 100644
--- a/vm/Globals.h
+++ b/vm/Globals.h
@@ -748,8 +748,16 @@
/* Flag to count trace execution */
bool profile;
+ /* Vector to disable selected optimizations */
+ int disableOpt;
+
/* Table to track the overall and trace statistics of hot methods */
HashTable* methodStatsTable;
+
+#if defined(WITH_SELF_VERIFICATION)
+ /* Spin when error is detected, volatile so GDB can reset it */
+ volatile bool selfVerificationSpin;
+#endif
};
extern struct DvmJitGlobals gDvmJit;
diff --git a/vm/IndirectRefTable.c b/vm/IndirectRefTable.c
index f7c7647..bea0a0f 100644
--- a/vm/IndirectRefTable.c
+++ b/vm/IndirectRefTable.c
@@ -35,6 +35,12 @@
#ifndef NDEBUG
memset(pRef->table, 0xd1, initialCount * sizeof(Object*));
#endif
+
+ pRef->slotData =
+ (IndirectRefSlot*) calloc(maxCount, sizeof(IndirectRefSlot));
+ if (pRef->slotData == NULL)
+ return false;
+
pRef->segmentState.all = IRT_FIRST_SEGMENT;
pRef->allocEntries = initialCount;
pRef->maxEntries = maxCount;
@@ -79,8 +85,8 @@
return false;
}
- LOGV("--- after pop, top=%d holes=%d\n",
- sst.parts.topIndex, sst.parts.numHoles);
+ LOGV("IRT %p[%d]: pop, top=%d holes=%d\n",
+ pRef, pRef->kind, sst.parts.topIndex, sst.parts.numHoles);
return true;
}
@@ -91,15 +97,45 @@
static bool checkEntry(IndirectRefTable* pRef, IndirectRef iref, int idx)
{
Object* obj = pRef->table[idx];
- IndirectRef checkRef = dvmObjectToIndirectRef(obj, idx, pRef->kind);
+ IndirectRef checkRef = dvmObjectToIndirectRef(pRef, obj, idx, pRef->kind);
if (checkRef != iref) {
- LOGW("iref mismatch: %p vs %p\n", iref, checkRef);
+ LOGW("IRT %p[%d]: iref mismatch (req=%p vs cur=%p)\n",
+ pRef, pRef->kind, iref, checkRef);
return false;
}
return true;
}
/*
+ * Update extended debug info when an entry is added.
+ *
+ * We advance the serial number, invalidating any outstanding references to
+ * this slot.
+ */
+static inline void updateSlotAdd(IndirectRefTable* pRef, Object* obj, int slot)
+{
+ if (pRef->slotData != NULL) {
+ IndirectRefSlot* pSlot = &pRef->slotData[slot];
+ pSlot->serial++;
+ //LOGI("+++ add [%d] slot %d (%p->%p), serial=%d\n",
+ // pRef->kind, slot, obj, iref, pSlot->serial);
+ pSlot->previous[pSlot->serial % kIRTPrevCount] = obj;
+ }
+}
+
+/*
+ * Update extended debug info when an entry is removed.
+ */
+static inline void updateSlotRemove(IndirectRefTable* pRef, int slot)
+{
+ if (pRef->slotData != NULL) {
+ IndirectRefSlot* pSlot = &pRef->slotData[slot];
+ //LOGI("+++ remove [%d] slot %d, serial now %d\n",
+ // pRef->kind, slot, pSlot->serial);
+ }
+}
+
+/*
* Add "obj" to "pRef".
*/
IndirectRef dvmAddToIndirectRefTable(IndirectRefTable* pRef, u4 cookie,
@@ -161,12 +197,15 @@
while (*--pScan != NULL) {
assert(pScan >= pRef->table + bottomIndex);
}
- result = dvmObjectToIndirectRef(obj, pScan - pRef->table, pRef->kind);
+ updateSlotAdd(pRef, obj, pScan - pRef->table);
+ result = dvmObjectToIndirectRef(pRef, obj, pScan - pRef->table,
+ pRef->kind);
*pScan = obj;
pRef->segmentState.parts.numHoles--;
} else {
/* add to the end */
- result = dvmObjectToIndirectRef(obj, topIndex, pRef->kind);
+ updateSlotAdd(pRef, obj, topIndex);
+ result = dvmObjectToIndirectRef(pRef, obj, topIndex, pRef->kind);
pRef->table[topIndex++] = obj;
pRef->segmentState.parts.topIndex = topIndex;
}
@@ -220,6 +259,9 @@
* specified by the cookie, we don't remove anything. This is the behavior
* required by JNI's DeleteLocalRef function.
*
+ * Note this is NOT called when a local frame is popped. This is only used
+ * for explict single removals.
+ *
* Returns "false" if nothing was removed.
*/
bool dvmRemoveFromIndirectRefTable(IndirectRefTable* pRef, u4 cookie,
@@ -255,6 +297,7 @@
*/
if (!checkEntry(pRef, iref, idx))
return false;
+ updateSlotRemove(pRef, idx);
#ifndef NDEBUG
pRef->table[idx] = (IndirectRef) 0xd3d3d3d3;
@@ -290,6 +333,7 @@
}
if (!checkEntry(pRef, iref, idx))
return false;
+ updateSlotRemove(pRef, idx);
pRef->table[idx] = NULL;
pRef->segmentState.parts.numHoles++;
@@ -408,7 +452,7 @@
qsort(tableCopy, count, sizeof(Object*), compareObject);
refs = tableCopy; // use sorted list
- {
+ if (false) {
int q;
for (q = 0; q < count; q++)
LOGI("%d %p\n", q, refs[q]);
diff --git a/vm/IndirectRefTable.h b/vm/IndirectRefTable.h
index c03353b..6a4db04 100644
--- a/vm/IndirectRefTable.h
+++ b/vm/IndirectRefTable.h
@@ -98,6 +98,16 @@
} IndirectRefKind;
/*
+ * Extended debugging structure. We keep a parallel array of these, one
+ * per slot in the table.
+ */
+#define kIRTPrevCount 4
+typedef struct IndirectRefSlot {
+ u4 serial; /* slot serial */
+ Object* previous[kIRTPrevCount];
+} IndirectRefSlot;
+
+/*
* Table definition.
*
* For the global reference table, the expected common operations are
@@ -179,6 +189,7 @@
Object** table; /* bottom of the stack */
/* private */
+ IndirectRefSlot* slotData; /* extended debugging info */
int allocEntries; /* #of entries we have space for */
int maxEntries; /* max #of entries allowed */
IndirectRefKind kind; /* bit mask, ORed into all irefs */
@@ -198,12 +209,14 @@
* The object pointer itself is subject to relocation in some GC
* implementations, so we shouldn't really be using it here.
*/
-INLINE IndirectRef dvmObjectToIndirectRef(Object* obj, u4 tableIndex,
- IndirectRefKind kind)
+INLINE IndirectRef dvmObjectToIndirectRef(IndirectRefTable* pRef,
+ Object* obj, u4 tableIndex, IndirectRefKind kind)
{
assert(tableIndex < 65536);
- u4 objChunk = (((u4) obj >> 3) ^ ((u4) obj >> 19)) & 0x3fff;
- u4 uref = objChunk << 18 | (tableIndex << 2) | kind;
+ //u4 objChunk = (((u4) obj >> 3) ^ ((u4) obj >> 19)) & 0x3fff;
+ //u4 uref = objChunk << 18 | (tableIndex << 2) | kind;
+ u4 serialChunk = pRef->slotData[tableIndex].serial;
+ u4 uref = serialChunk << 20 | (tableIndex << 2) | kind;
return (IndirectRef) uref;
}
@@ -270,7 +283,7 @@
*
* IMPORTANT: this is implemented as a single instruction in mterp, rather
* than a call here. You can add debugging aids for the C-language
- * interpreters, but the basic implementation may not change.
+ * interpreters, but the basic implementation must not change.
*/
INLINE void dvmPopIndirectRefTableSegment(IndirectRefTable* pRef, u4 cookie)
{
@@ -323,7 +336,8 @@
/* up against alloc or max limit, call the fancy version */
return dvmAddToIndirectRefTable(pRef, cookie, obj);
} else {
- IndirectRef result = dvmObjectToIndirectRef(obj, topIndex, pRef->kind);
+ IndirectRef result = dvmObjectToIndirectRef(pRef, obj, topIndex,
+ pRef->kind);
pRef->table[topIndex++] = obj;
pRef->segmentState.parts.topIndex = topIndex;
return result;
diff --git a/vm/Init.c b/vm/Init.c
index c46de25..7f83bc5 100644
--- a/vm/Init.c
+++ b/vm/Init.c
@@ -120,6 +120,7 @@
"(eg Ljava/lang/String\\;replace)\n");
dvmFprintf(stderr, " -Xjitverbose\n");
dvmFprintf(stderr, " -Xjitprofile\n");
+ dvmFprintf(stderr, " -Xjitdisableopt\n");
#endif
dvmFprintf(stderr, "\n");
dvmFprintf(stderr, "Configured with:"
@@ -185,7 +186,10 @@
" resolver_cache_disabled"
#endif
#if defined(WITH_JIT)
- " with_jit"
+ " jit"
+#endif
+#if defined(WITH_SELF_VERIFICATION)
+ " self_verification"
#endif
);
#ifdef DVM_SHOW_EXCEPTION
@@ -907,6 +911,8 @@
gDvmJit.printMe = true;
} else if (strncmp(argv[i], "-Xjitprofile", 12) == 0) {
gDvmJit.profile = true;
+ } else if (strncmp(argv[i], "-Xjitdisableopt:", 16) == 0) {
+ sscanf(argv[i] + 16, "%x", &gDvmJit.disableOpt);
#endif
} else if (strncmp(argv[i], "-Xdeadlockpredict:", 18) == 0) {
@@ -1362,8 +1368,10 @@
(int)(endJdwp-startJdwp), (int)(endJdwp-startHeap));
#ifdef WITH_JIT
- if (!dvmJitStartup())
- return false;
+ if (gDvm.executionMode == kExecutionModeJit) {
+ if (!dvmJitStartup())
+ return false;
+ }
#endif
return true;
@@ -1552,8 +1560,10 @@
dvmStdioConverterShutdown();
#ifdef WITH_JIT
- /* tell the compiler to shut down if it was started */
- dvmJitShutdown();
+ if (gDvm.executionMode == kExecutionModeJit) {
+ /* shut down the compiler thread */
+ dvmJitShutdown();
+ }
#endif
/*
diff --git a/vm/InlineNative.c b/vm/InlineNative.c
index f829360..ec8a1fb 100644
--- a/vm/InlineNative.c
+++ b/vm/InlineNative.c
@@ -129,14 +129,14 @@
return false;
//LOGI("String.charAt this=0x%08x index=%d\n", arg0, arg1);
- count = dvmGetFieldInt((Object*) arg0, gDvm.offJavaLangString_count);
+ count = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_COUNT);
if ((s4) arg1 < 0 || (s4) arg1 >= count) {
dvmThrowException("Ljava/lang/StringIndexOutOfBoundsException;", NULL);
return false;
} else {
- offset = dvmGetFieldInt((Object*) arg0, gDvm.offJavaLangString_offset);
+ offset = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_OFFSET);
chars = (ArrayObject*)
- dvmGetFieldObject((Object*) arg0, gDvm.offJavaLangString_value);
+ dvmGetFieldObject((Object*) arg0, STRING_FIELDOFF_VALUE);
pResult->i = ((const u2*) chars->contents)[arg1 + offset];
return true;
@@ -157,17 +157,17 @@
int thisOffset, compOffset, thisCount, compCount;
thisCount =
- dvmGetFieldInt((Object*) thisStrObj, gDvm.offJavaLangString_count);
+ dvmGetFieldInt((Object*) thisStrObj, STRING_FIELDOFF_COUNT);
compCount =
- dvmGetFieldInt((Object*) compStrObj, gDvm.offJavaLangString_count);
+ dvmGetFieldInt((Object*) compStrObj, STRING_FIELDOFF_COUNT);
thisOffset =
- dvmGetFieldInt((Object*) thisStrObj, gDvm.offJavaLangString_offset);
+ dvmGetFieldInt((Object*) thisStrObj, STRING_FIELDOFF_OFFSET);
compOffset =
- dvmGetFieldInt((Object*) compStrObj, gDvm.offJavaLangString_offset);
+ dvmGetFieldInt((Object*) compStrObj, STRING_FIELDOFF_OFFSET);
thisArray = (ArrayObject*)
- dvmGetFieldObject((Object*) thisStrObj, gDvm.offJavaLangString_value);
+ dvmGetFieldObject((Object*) thisStrObj, STRING_FIELDOFF_VALUE);
compArray = (ArrayObject*)
- dvmGetFieldObject((Object*) compStrObj, gDvm.offJavaLangString_value);
+ dvmGetFieldObject((Object*) compStrObj, STRING_FIELDOFF_VALUE);
thisStr = dvmCreateCstrFromString(thisStrObj);
compStr = dvmCreateCstrFromString(compStrObj);
@@ -221,16 +221,16 @@
const u2* compChars;
int i, minCount, countDiff;
- thisCount = dvmGetFieldInt((Object*) arg0, gDvm.offJavaLangString_count);
- compCount = dvmGetFieldInt((Object*) arg1, gDvm.offJavaLangString_count);
+ thisCount = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_COUNT);
+ compCount = dvmGetFieldInt((Object*) arg1, STRING_FIELDOFF_COUNT);
countDiff = thisCount - compCount;
minCount = (countDiff < 0) ? thisCount : compCount;
- thisOffset = dvmGetFieldInt((Object*) arg0, gDvm.offJavaLangString_offset);
- compOffset = dvmGetFieldInt((Object*) arg1, gDvm.offJavaLangString_offset);
+ thisOffset = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_OFFSET);
+ compOffset = dvmGetFieldInt((Object*) arg1, STRING_FIELDOFF_OFFSET);
thisArray = (ArrayObject*)
- dvmGetFieldObject((Object*) arg0, gDvm.offJavaLangString_value);
+ dvmGetFieldObject((Object*) arg0, STRING_FIELDOFF_VALUE);
compArray = (ArrayObject*)
- dvmGetFieldObject((Object*) arg1, gDvm.offJavaLangString_value);
+ dvmGetFieldObject((Object*) arg1, STRING_FIELDOFF_VALUE);
thisChars = ((const u2*) thisArray->contents) + thisOffset;
compChars = ((const u2*) compArray->contents) + compOffset;
@@ -321,19 +321,19 @@
int i;
/* quick length check */
- thisCount = dvmGetFieldInt((Object*) arg0, gDvm.offJavaLangString_count);
- compCount = dvmGetFieldInt((Object*) arg1, gDvm.offJavaLangString_count);
+ thisCount = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_COUNT);
+ compCount = dvmGetFieldInt((Object*) arg1, STRING_FIELDOFF_COUNT);
if (thisCount != compCount) {
pResult->i = false;
return true;
}
- thisOffset = dvmGetFieldInt((Object*) arg0, gDvm.offJavaLangString_offset);
- compOffset = dvmGetFieldInt((Object*) arg1, gDvm.offJavaLangString_offset);
+ thisOffset = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_OFFSET);
+ compOffset = dvmGetFieldInt((Object*) arg1, STRING_FIELDOFF_OFFSET);
thisArray = (ArrayObject*)
- dvmGetFieldObject((Object*) arg0, gDvm.offJavaLangString_value);
+ dvmGetFieldObject((Object*) arg0, STRING_FIELDOFF_VALUE);
compArray = (ArrayObject*)
- dvmGetFieldObject((Object*) arg1, gDvm.offJavaLangString_value);
+ dvmGetFieldObject((Object*) arg1, STRING_FIELDOFF_VALUE);
thisChars = ((const u2*) thisArray->contents) + thisOffset;
compChars = ((const u2*) compArray->contents) + compOffset;
@@ -383,7 +383,90 @@
if (!dvmValidateObject((Object*) arg0))
return false;
- pResult->i = dvmGetFieldInt((Object*) arg0, gDvm.offJavaLangString_count);
+ pResult->i = dvmGetFieldInt((Object*) arg0, STRING_FIELDOFF_COUNT);
+ return true;
+}
+
+/*
+ * Determine the index of the first character matching "ch". The string
+ * to search is described by "chars", "offset", and "count".
+ *
+ * The "ch" parameter is allowed to be > 0xffff. Our Java-language
+ * implementation does not currently handle this, so neither do we.
+ *
+ * The "start" parameter must be clamped to [0..count].
+ *
+ * Returns -1 if no match is found.
+ */
+static inline int indexOfCommon(Object* strObj, int ch, int start)
+{
+ //if ((ch & 0xffff) != ch) /* 32-bit code point */
+ // return -1;
+
+ /* pull out the basic elements */
+ ArrayObject* charArray =
+ (ArrayObject*) dvmGetFieldObject(strObj, STRING_FIELDOFF_VALUE);
+ const u2* chars = (const u2*) charArray->contents;
+ int offset = dvmGetFieldInt(strObj, STRING_FIELDOFF_OFFSET);
+ int count = dvmGetFieldInt(strObj, STRING_FIELDOFF_COUNT);
+ //LOGI("String.indexOf(0x%08x, 0x%04x, %d) off=%d count=%d\n",
+ // (u4) strObj, ch, start, offset, count);
+
+ /* factor out the offset */
+ chars += offset;
+
+ if (start < 0)
+ start = 0;
+
+#if 0
+ /* 16-bit loop, simple */
+ while (start < count) {
+ if (chars[start] == ch)
+ return start;
+ start++;
+ }
+#else
+ /* 16-bit loop, slightly better on ARM */
+ const u2* ptr = chars + start;
+ const u2* endPtr = chars + count;
+ while (ptr < endPtr) {
+ if (*ptr++ == ch)
+ return (ptr-1) - chars;
+ }
+#endif
+
+ return -1;
+}
+
+/*
+ * public int indexOf(int c)
+ *
+ * Scan forward through the string for a matching character.
+ */
+static bool javaLangString_indexOf_I(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+ JValue* pResult)
+{
+ /* null reference check on "this" */
+ if (!dvmValidateObject((Object*) arg0))
+ return false;
+
+ pResult->i = indexOfCommon((Object*) arg0, arg1, 0);
+ return true;
+}
+
+/*
+ * public int indexOf(int c, int start)
+ *
+ * Scan forward through the string for a matching character.
+ */
+static bool javaLangString_indexOf_II(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+ JValue* pResult)
+{
+ /* null reference check on "this" */
+ if (!dvmValidateObject((Object*) arg0))
+ return false;
+
+ pResult->i = indexOfCommon((Object*) arg0, arg1, arg2);
return true;
}
@@ -550,8 +633,11 @@
* pointer field.
*
* IMPORTANT: you must update DALVIK_VM_BUILD in DalvikVersion.h if you make
- * changes to this table. Must also be kept in sync with NativeInlineOps
- * enum in InlineNative.h.
+ * changes to this table.
+ *
+ * NOTE: If present, the JIT will also need to know about changes
+ * to this table. Update the NativeInlineOps enum in InlineNative.h and
+ * the dispatch code in compiler/codegen/<target>/Codegen.c.
*/
const InlineOperation gDvmInlineOpsTable[] = {
{ org_apache_harmony_dalvik_NativeTestTarget_emptyInlineMethod,
@@ -564,6 +650,10 @@
"Ljava/lang/String;", "compareTo", "(Ljava/lang/String;)I" },
{ javaLangString_equals,
"Ljava/lang/String;", "equals", "(Ljava/lang/Object;)Z" },
+ { javaLangString_indexOf_I,
+ "Ljava/lang/String;", "indexOf", "(I)I" },
+ { javaLangString_indexOf_II,
+ "Ljava/lang/String;", "indexOf", "(II)I" },
{ javaLangString_length,
"Ljava/lang/String;", "length", "()I" },
@@ -587,7 +677,6 @@
"Ljava/lang/Math;", "sin", "(D)D" },
};
-
/*
* Allocate some tables.
*/
diff --git a/vm/InlineNative.h b/vm/InlineNative.h
index 98398da..300c94c 100644
--- a/vm/InlineNative.h
+++ b/vm/InlineNative.h
@@ -54,16 +54,18 @@
INLINE_STRING_CHARAT = 1,
INLINE_STRING_COMPARETO = 2,
INLINE_STRING_EQUALS = 3,
- INLINE_STRING_LENGTH = 4,
- INLINE_MATH_ABS_INT = 5,
- INLINE_MATH_ABS_LONG = 6,
- INLINE_MATH_ABS_FLOAT = 7,
- INLINE_MATH_ABS_DOUBLE = 8,
- INLINE_MATH_MIN_INT = 9,
- INLINE_MATH_MAX_INT = 10,
- INLINE_MATH_SQRT = 11,
- INLINE_MATH_COS = 12,
- INLINE_MATH_SIN = 13,
+ INLINE_STRING_INDEXOF_I = 4,
+ INLINE_STRING_INDEXOF_II = 5,
+ INLINE_STRING_LENGTH = 6,
+ INLINE_MATH_ABS_INT = 7,
+ INLINE_MATH_ABS_LONG = 8,
+ INLINE_MATH_ABS_FLOAT = 9,
+ INLINE_MATH_ABS_DOUBLE = 10,
+ INLINE_MATH_MIN_INT = 11,
+ INLINE_MATH_MAX_INT = 12,
+ INLINE_MATH_SQRT = 13,
+ INLINE_MATH_COS = 14,
+ INLINE_MATH_SIN = 15,
} NativeInlineOps;
/*
diff --git a/vm/Jni.c b/vm/Jni.c
index 10afcaa..d7d1122 100644
--- a/vm/Jni.c
+++ b/vm/Jni.c
@@ -3102,7 +3102,7 @@
JNI_ENTER();
ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
- jint retval;
+ jint retval = JNI_OK;
int i;
if (gDvm.verboseJni) {
@@ -3115,12 +3115,9 @@
methods[i].signature, methods[i].fnPtr))
{
retval = JNI_ERR;
- goto bail;
}
}
- retval = JNI_OK;
-bail:
JNI_EXIT();
return retval;
}
@@ -4218,4 +4215,3 @@
free(argv);
return result;
}
-
diff --git a/vm/Misc.c b/vm/Misc.c
index f8f7256..193e0bd 100644
--- a/vm/Misc.c
+++ b/vm/Misc.c
@@ -345,6 +345,39 @@
}
/*
+ * Copy a whole vector to the other. Only do that when the both vectors have
+ * the same size and attribute.
+ */
+bool dvmCopyBitVector(BitVector *dest, const BitVector *src)
+{
+ if (dest->storageSize != src->storageSize ||
+ dest->expandable != src->expandable)
+ return false;
+ memcpy(dest->storage, src->storage, sizeof(u4) * dest->storageSize);
+ return true;
+}
+
+/*
+ * Intersect two bit vectores and merge the result on top of the pre-existing
+ * value in the dest vector.
+ */
+bool dvmIntersectBitVectors(BitVector *dest, const BitVector *src1,
+ const BitVector *src2)
+{
+ if (dest->storageSize != src1->storageSize ||
+ dest->storageSize != src2->storageSize ||
+ dest->expandable != src1->expandable ||
+ dest->expandable != src2->expandable)
+ return false;
+
+ int i;
+ for (i = 0; i < dest->storageSize; i++) {
+ dest->storage[i] |= src1->storage[i] & src2->storage[i];
+ }
+ return true;
+}
+
+/*
* Return a newly-allocated string in which all occurrences of '.' have
* been changed to '/'. If we find a '/' in the original string, NULL
* is returned to avoid ambiguity.
@@ -354,6 +387,9 @@
char* newStr = strdup(str);
char* cp = newStr;
+ if (newStr == NULL)
+ return NULL;
+
while (*cp != '\0') {
if (*cp == '/') {
assert(false);
@@ -384,6 +420,9 @@
}
newStr = malloc(at + 1); /* Add one for the '\0'. */
+ if (newStr == NULL)
+ return NULL;
+
newStr[at] = '\0';
while (at > 0) {
diff --git a/vm/Misc.h b/vm/Misc.h
index 14635a3..3e04f84 100644
--- a/vm/Misc.h
+++ b/vm/Misc.h
@@ -164,6 +164,16 @@
/* count the number of bits that have been set */
int dvmCountSetBits(const BitVector* pBits);
+/* copy one vector to the other compatible one */
+bool dvmCopyBitVector(BitVector *dest, const BitVector *src);
+
+/*
+ * Intersect two bit vectores and merge the result on top of the pre-existing
+ * value in the dest vector.
+ */
+bool dvmIntersectBitVectors(BitVector *dest, const BitVector *src1,
+ const BitVector *src2);
+
#define kBitVectorGrowth 4 /* increase by 4 u4s when limit hit */
diff --git a/vm/Sync.c b/vm/Sync.c
index 1f81349..8528c0f 100644
--- a/vm/Sync.c
+++ b/vm/Sync.c
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
/*
* Fundamental synchronization mechanisms.
*
@@ -985,8 +986,10 @@
LOG_THIN("(%d) lock 0x%08x fattened by wait() to count %d\n",
self->threadId, (uint)&obj->lock, mon->lockCount);
+
/* Make the monitor public now that it's in the right state.
*/
+ MEM_BARRIER();
obj->lock.mon = mon;
}
diff --git a/vm/Thread.c b/vm/Thread.c
index be3e952..7ca3dc7 100644
--- a/vm/Thread.c
+++ b/vm/Thread.c
@@ -36,6 +36,11 @@
#include <sys/prctl.h>
#endif
+#if defined(WITH_SELF_VERIFICATION)
+#include "interp/Jit.h" // need for self verification
+#endif
+
+
/* desktop Linux needs a little help with gettid() */
#if defined(HAVE_GETTID) && !defined(HAVE_ANDROID_OS)
#define __KERNEL__
@@ -895,6 +900,11 @@
if (thread == NULL)
return NULL;
+#if defined(WITH_SELF_VERIFICATION)
+ if (dvmSelfVerificationShadowSpaceAlloc(thread) == NULL)
+ return NULL;
+#endif
+
assert(interpStackSize >= kMinStackSize && interpStackSize <=kMaxStackSize);
thread->status = THREAD_INITIALIZING;
@@ -914,6 +924,9 @@
#ifdef MALLOC_INTERP_STACK
stackBottom = (u1*) malloc(interpStackSize);
if (stackBottom == NULL) {
+#if defined(WITH_SELF_VERIFICATION)
+ dvmSelfVerificationShadowSpaceFree(thread);
+#endif
free(thread);
return NULL;
}
@@ -922,6 +935,9 @@
stackBottom = mmap(NULL, interpStackSize, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
if (stackBottom == MAP_FAILED) {
+#if defined(WITH_SELF_VERIFICATION)
+ dvmSelfVerificationShadowSpaceFree(thread);
+#endif
free(thread);
return NULL;
}
@@ -1061,6 +1077,9 @@
if (&thread->jniMonitorRefTable.table != NULL)
dvmClearReferenceTable(&thread->jniMonitorRefTable);
+#if defined(WITH_SELF_VERIFICATION)
+ dvmSelfVerificationShadowSpaceFree(thread);
+#endif
free(thread);
}
diff --git a/vm/Thread.h b/vm/Thread.h
index 1bb5314..179a920 100644
--- a/vm/Thread.h
+++ b/vm/Thread.h
@@ -220,6 +220,11 @@
const u2* currentPc2;
#endif
+#if defined(WITH_SELF_VERIFICATION)
+ /* Buffer for register state during self verification */
+ struct ShadowSpace* shadowSpace;
+#endif
+
/* system thread state */
SystemThread* systemThread;
} Thread;
diff --git a/vm/UtfString.c b/vm/UtfString.c
index dfb76bc..8e20a0f 100644
--- a/vm/UtfString.c
+++ b/vm/UtfString.c
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
/*
* UTF-8 and Unicode string manipulation, plus java/lang/String convenience
* functions.
@@ -69,6 +70,30 @@
return false;
}
+ bool badValue = false;
+ if (gDvm.offJavaLangString_value != STRING_FIELDOFF_VALUE) {
+ LOGE("InlineNative: String.value offset = %d, expected %d\n",
+ gDvm.offJavaLangString_value, STRING_FIELDOFF_VALUE);
+ badValue = true;
+ }
+ if (gDvm.offJavaLangString_count != STRING_FIELDOFF_COUNT) {
+ LOGE("InlineNative: String.count offset = %d, expected %d\n",
+ gDvm.offJavaLangString_count, STRING_FIELDOFF_COUNT);
+ badValue = true;
+ }
+ if (gDvm.offJavaLangString_offset != STRING_FIELDOFF_OFFSET) {
+ LOGE("InlineNative: String.offset offset = %d, expected %d\n",
+ gDvm.offJavaLangString_offset, STRING_FIELDOFF_OFFSET);
+ badValue = true;
+ }
+ if (gDvm.offJavaLangString_hashCode != STRING_FIELDOFF_HASHCODE) {
+ LOGE("InlineNative: String.hashCode offset = %d, expected %d\n",
+ gDvm.offJavaLangString_hashCode, STRING_FIELDOFF_HASHCODE);
+ badValue = true;
+ }
+ if (badValue)
+ return false;
+
gDvm.javaLangStringReady = 1;
return true;
@@ -213,11 +238,11 @@
}
u4 dvmComputeStringHash(StringObject* strObj) {
ArrayObject* chars = (ArrayObject*) dvmGetFieldObject((Object*) strObj,
- gDvm.offJavaLangString_value);
+ STRING_FIELDOFF_VALUE);
int offset, len;
- len = dvmGetFieldInt((Object*) strObj, gDvm.offJavaLangString_count);
- offset = dvmGetFieldInt((Object*) strObj, gDvm.offJavaLangString_offset);
+ len = dvmGetFieldInt((Object*) strObj, STRING_FIELDOFF_COUNT);
+ offset = dvmGetFieldInt((Object*) strObj, STRING_FIELDOFF_OFFSET);
return dvmComputeUtf16Hash((u2*) chars->contents + offset, len);
}
@@ -285,11 +310,11 @@
dvmConvertUtf8ToUtf16((u2*)chars->contents, utf8Str);
hashCode = dvmComputeUtf16Hash((u2*) chars->contents, utf16Length);
- dvmSetFieldObject((Object*)newObj, gDvm.offJavaLangString_value,
+ dvmSetFieldObject((Object*)newObj, STRING_FIELDOFF_VALUE,
(Object*)chars);
dvmReleaseTrackedAllocIFN((Object*) chars, NULL, allocFlags);
- dvmSetFieldInt((Object*)newObj, gDvm.offJavaLangString_count, utf16Length);
- dvmSetFieldInt((Object*)newObj, gDvm.offJavaLangString_hashCode, hashCode);
+ dvmSetFieldInt((Object*)newObj, STRING_FIELDOFF_COUNT, utf16Length);
+ dvmSetFieldInt((Object*)newObj, STRING_FIELDOFF_HASHCODE, hashCode);
/* leave offset set to zero */
/* debugging stuff */
@@ -339,11 +364,11 @@
memcpy(chars->contents, unichars, len * sizeof(u2));
hashCode = dvmComputeUtf16Hash((u2*) chars->contents, len);
- dvmSetFieldObject((Object*)newObj, gDvm.offJavaLangString_value,
+ dvmSetFieldObject((Object*)newObj, STRING_FIELDOFF_VALUE,
(Object*)chars);
dvmReleaseTrackedAlloc((Object*) chars, NULL);
- dvmSetFieldInt((Object*)newObj, gDvm.offJavaLangString_count, len);
- dvmSetFieldInt((Object*)newObj, gDvm.offJavaLangString_hashCode, hashCode);
+ dvmSetFieldInt((Object*)newObj, STRING_FIELDOFF_COUNT, len);
+ dvmSetFieldInt((Object*)newObj, STRING_FIELDOFF_HASHCODE, hashCode);
/* leave offset set to zero */
/* debugging stuff */
@@ -371,10 +396,10 @@
if (jstr == NULL)
return NULL;
- len = dvmGetFieldInt((Object*) jstr, gDvm.offJavaLangString_count);
- offset = dvmGetFieldInt((Object*) jstr, gDvm.offJavaLangString_offset);
+ len = dvmGetFieldInt((Object*) jstr, STRING_FIELDOFF_COUNT);
+ offset = dvmGetFieldInt((Object*) jstr, STRING_FIELDOFF_OFFSET);
chars = (ArrayObject*) dvmGetFieldObject((Object*) jstr,
- gDvm.offJavaLangString_value);
+ STRING_FIELDOFF_VALUE);
data = (const u2*) chars->contents + offset;
assert(offset + len <= (int) chars->length);
@@ -416,10 +441,10 @@
if (jstr == NULL)
return 0; // should we throw something? assert?
- len = dvmGetFieldInt((Object*) jstr, gDvm.offJavaLangString_count);
- offset = dvmGetFieldInt((Object*) jstr, gDvm.offJavaLangString_offset);
+ len = dvmGetFieldInt((Object*) jstr, STRING_FIELDOFF_COUNT);
+ offset = dvmGetFieldInt((Object*) jstr, STRING_FIELDOFF_OFFSET);
chars = (ArrayObject*) dvmGetFieldObject((Object*) jstr,
- gDvm.offJavaLangString_value);
+ STRING_FIELDOFF_VALUE);
data = (const u2*) chars->contents + offset;
assert(offset + len <= (int) chars->length);
@@ -431,7 +456,7 @@
*/
int dvmStringLen(StringObject* jstr)
{
- return dvmGetFieldInt((Object*) jstr, gDvm.offJavaLangString_count);
+ return dvmGetFieldInt((Object*) jstr, STRING_FIELDOFF_COUNT);
}
/*
@@ -440,7 +465,7 @@
ArrayObject* dvmStringCharArray(StringObject* jstr)
{
return (ArrayObject*) dvmGetFieldObject((Object*) jstr,
- gDvm.offJavaLangString_value);
+ STRING_FIELDOFF_VALUE);
}
/*
@@ -451,9 +476,9 @@
ArrayObject* chars;
int offset;
- offset = dvmGetFieldInt((Object*) jstr, gDvm.offJavaLangString_offset);
+ offset = dvmGetFieldInt((Object*) jstr, STRING_FIELDOFF_OFFSET);
chars = (ArrayObject*) dvmGetFieldObject((Object*) jstr,
- gDvm.offJavaLangString_value);
+ STRING_FIELDOFF_VALUE);
return (const u2*) chars->contents + offset;
}
@@ -476,17 +501,17 @@
assert(gDvm.javaLangStringReady > 0);
/* get offset and length into char array; all values are in 16-bit units */
- len1 = dvmGetFieldInt((Object*) strObj1, gDvm.offJavaLangString_count);
- offset1 = dvmGetFieldInt((Object*) strObj1, gDvm.offJavaLangString_offset);
- len2 = dvmGetFieldInt((Object*) strObj2, gDvm.offJavaLangString_count);
- offset2 = dvmGetFieldInt((Object*) strObj2, gDvm.offJavaLangString_offset);
+ len1 = dvmGetFieldInt((Object*) strObj1, STRING_FIELDOFF_COUNT);
+ offset1 = dvmGetFieldInt((Object*) strObj1, STRING_FIELDOFF_OFFSET);
+ len2 = dvmGetFieldInt((Object*) strObj2, STRING_FIELDOFF_COUNT);
+ offset2 = dvmGetFieldInt((Object*) strObj2, STRING_FIELDOFF_OFFSET);
if (len1 != len2)
return len1 - len2;
chars1 = (ArrayObject*) dvmGetFieldObject((Object*) strObj1,
- gDvm.offJavaLangString_value);
+ STRING_FIELDOFF_VALUE);
chars2 = (ArrayObject*) dvmGetFieldObject((Object*) strObj2,
- gDvm.offJavaLangString_value);
+ STRING_FIELDOFF_VALUE);
/* damage here actually indicates a broken java/lang/String */
assert(offset1 + len1 <= (int) chars1->length);
diff --git a/vm/UtfString.h b/vm/UtfString.h
index ca500a7..8f0f972 100644
--- a/vm/UtfString.h
+++ b/vm/UtfString.h
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
/*
* UTF-8 and Unicode string manipulation functions, plus convenience
* functions for working with java/lang/String.
@@ -21,6 +22,30 @@
#define _DALVIK_STRING
/*
+ * (This is private to UtfString.c, but we cheat a bit and also use it
+ * for InlineNative.c. Not really worth creating a separate header.)
+ *
+ * We can avoid poking around in gDvm by hard-coding the expected values of
+ * the String field offsets. This will be annoying if String is in flux
+ * or the VM field layout is changing, so we use defines here to make it
+ * easy to switch back to the gDvm version.
+ *
+ * The values are checked for correctness during startup.
+ */
+//#define USE_GLOBAL_STRING_DEFS
+#ifdef USE_GLOBAL_STRING_DEFS
+# define STRING_FIELDOFF_VALUE gDvm.offJavaLangString_value
+# define STRING_FIELDOFF_OFFSET gDvm.offJavaLangString_offset
+# define STRING_FIELDOFF_COUNT gDvm.offJavaLangString_count
+# define STRING_FIELDOFF_HASHCODE gDvm.offJavaLangString_hashCode
+#else
+# define STRING_FIELDOFF_VALUE 8
+# define STRING_FIELDOFF_HASHCODE 12
+# define STRING_FIELDOFF_OFFSET 16
+# define STRING_FIELDOFF_COUNT 20
+#endif
+
+/*
* Hash function for modified UTF-8 strings.
*/
u4 dvmComputeUtf8Hash(const char* str);
diff --git a/vm/alloc/Heap.c b/vm/alloc/Heap.c
index 17d6a5c..33efa85 100644
--- a/vm/alloc/Heap.c
+++ b/vm/alloc/Heap.c
@@ -573,10 +573,6 @@
}
}
-#if WITH_OBJECT_HEADERS
- hc->header = OBJECT_HEADER;
- hc->birthGeneration = gGeneration;
-#endif
ptr = hc->data;
/* The caller may not want us to collect this object.
diff --git a/vm/alloc/HeapInternal.h b/vm/alloc/HeapInternal.h
index fafb87a..a2d31fe 100644
--- a/vm/alloc/HeapInternal.h
+++ b/vm/alloc/HeapInternal.h
@@ -29,27 +29,7 @@
#define ptr2chunk(p) (((DvmHeapChunk *)(p)) - 1)
#define chunk2ptr(p) ((void *)(((DvmHeapChunk *)(p)) + 1))
-#define WITH_OBJECT_HEADERS 0
-#if WITH_OBJECT_HEADERS
-#define OBJECT_HEADER 0x11335577
-extern u2 gGeneration;
-#endif
-
typedef struct DvmHeapChunk {
-#if WITH_OBJECT_HEADERS
- u4 header;
- const Object *parent;
- const Object *parentOld;
- const Object *markFinger;
- const Object *markFingerOld;
- u2 birthGeneration;
- u2 markCount;
- u2 scanCount;
- u2 oldMarkGeneration;
- u2 markGeneration;
- u2 oldScanGeneration;
- u2 scanGeneration;
-#endif
#if WITH_HPROF && WITH_HPROF_STACK
u4 stackTraceSerialNumber;
#endif
diff --git a/vm/alloc/MarkSweep.c b/vm/alloc/MarkSweep.c
index 09cc25f..4bb917b 100644
--- a/vm/alloc/MarkSweep.c
+++ b/vm/alloc/MarkSweep.c
@@ -68,11 +68,6 @@
#define LOGV_SWEEP(...) LOGVV_GC("SWEEP: " __VA_ARGS__)
#define LOGV_REF(...) LOGVV_GC("REF: " __VA_ARGS__)
-#if WITH_OBJECT_HEADERS
-u2 gGeneration = 0;
-static const Object *gMarkParent = NULL;
-#endif
-
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
@@ -170,10 +165,6 @@
mc->numBitmaps = numBitmaps;
mc->finger = NULL;
-#if WITH_OBJECT_HEADERS
- gGeneration++;
-#endif
-
return true;
}
@@ -213,28 +204,6 @@
MARK_STACK_PUSH(ctx->stack, obj);
}
-#if WITH_OBJECT_HEADERS
- if (hc->scanGeneration != hc->markGeneration) {
- LOGE("markObject(0x%08x): wasn't scanned last time\n", (uint)obj);
- dvmAbort();
- }
- if (hc->markGeneration == gGeneration) {
- LOGE("markObject(0x%08x): already marked this generation\n",
- (uint)obj);
- dvmAbort();
- }
- hc->oldMarkGeneration = hc->markGeneration;
- hc->markGeneration = gGeneration;
- hc->markFingerOld = hc->markFinger;
- hc->markFinger = ctx->finger;
- if (gMarkParent != NULL) {
- hc->parentOld = hc->parent;
- hc->parent = gMarkParent;
- } else {
- hc->parent = (const Object *)((uintptr_t)hc->parent | 1);
- }
- hc->markCount++;
-#endif
#if WITH_HPROF
if (gDvm.gcHeap->hprofContext != NULL) {
hprofMarkRootObject(gDvm.gcHeap->hprofContext, obj, 0);
@@ -535,17 +504,6 @@
}
#endif
-#if WITH_OBJECT_HEADERS
- if (ptr2chunk(obj)->scanGeneration == gGeneration) {
- LOGE("object 0x%08x was already scanned this generation\n",
- (uintptr_t)obj);
- dvmAbort();
- }
- ptr2chunk(obj)->oldScanGeneration = ptr2chunk(obj)->scanGeneration;
- ptr2chunk(obj)->scanGeneration = gGeneration;
- ptr2chunk(obj)->scanCount++;
-#endif
-
/* Get and mark the class object for this particular instance.
*/
clazz = obj->clazz;
@@ -567,10 +525,6 @@
return;
}
-#if WITH_OBJECT_HEADERS
- gMarkParent = obj;
-#endif
-
assert(dvmIsValidObject((Object *)clazz));
markObjectNonNull((Object *)clazz, ctx);
@@ -720,10 +674,6 @@
scanClassObject((ClassObject *)obj, ctx);
}
}
-
-#if WITH_OBJECT_HEADERS
- gMarkParent = NULL;
-#endif
}
static void
@@ -1225,13 +1175,6 @@
hc = (DvmHeapChunk *)*ptrs++;
obj = (Object *)chunk2ptr(hc);
-#if WITH_OBJECT_HEADERS
- if (hc->markGeneration == gGeneration) {
- LOGE("sweeping marked object: 0x%08x\n", (uint)obj);
- dvmAbort();
- }
-#endif
-
/* Free the monitor associated with the object.
*/
dvmFreeObjectMonitor(obj);
@@ -1264,16 +1207,9 @@
{
int chunklen;
ClassObject *clazz = obj->clazz;
-#if WITH_OBJECT_HEADERS
- DvmHeapChunk chunk = *hc;
- chunk.header = ~OBJECT_HEADER | 1;
-#endif
chunklen = dvmHeapSourceChunkSize(hc);
memset(hc, 0xa5, chunklen);
obj->clazz = (ClassObject *)((uintptr_t)clazz ^ 0xffffffff);
-#if WITH_OBJECT_HEADERS
- *hc = chunk;
-#endif
}
#endif
}
diff --git a/vm/analysis/RegisterMap.c b/vm/analysis/RegisterMap.c
index 0e3445a..d1f2600 100644
--- a/vm/analysis/RegisterMap.c
+++ b/vm/analysis/RegisterMap.c
@@ -1036,6 +1036,7 @@
default:
LOGE("Unknown format %d in dvmGetExpandedRegisterMap\n", format);
dvmAbort();
+ newMap = NULL; // make gcc happy
}
if (newMap == NULL) {
diff --git a/vm/compiler/Compiler.c b/vm/compiler/Compiler.c
index 203a080..9db641e 100644
--- a/vm/compiler/Compiler.c
+++ b/vm/compiler/Compiler.c
@@ -21,7 +21,6 @@
#include "interp/Jit.h"
#include "CompilerInternals.h"
-
static inline bool workQueueLength(void)
{
return gDvmJit.compilerQueueLength;
@@ -101,13 +100,14 @@
static void *compilerThreadStart(void *arg)
{
+ dvmChangeStatus(NULL, THREAD_VMWAIT);
+
dvmLockMutex(&gDvmJit.compilerLock);
/*
* Since the compiler thread will not touch any objects on the heap once
* being created, we just fake its state as VMWAIT so that it can be a
* bit late when there is suspend request pending.
*/
- dvmChangeStatus(NULL, THREAD_VMWAIT);
while (!gDvmJit.haltCompilerThread) {
if (workQueueLength() == 0) {
int cc;
@@ -144,6 +144,13 @@
pthread_cond_signal(&gDvmJit.compilerQueueEmpty);
dvmUnlockMutex(&gDvmJit.compilerLock);
+ /*
+ * As part of detaching the thread we need to call into Java code to update
+ * the ThreadGroup, and we should not be in VMWAIT state while executing
+ * interpreted code.
+ */
+ dvmChangeStatus(NULL, THREAD_RUNNING);
+
LOGD("Compiler thread shutting down\n");
return NULL;
}
@@ -156,7 +163,7 @@
/* Allocate the code cache */
gDvmJit.codeCache = mmap(0, CODE_CACHE_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ MAP_PRIVATE | MAP_ANON, -1, 0);
if (gDvmJit.codeCache == MAP_FAILED) {
LOGE("Failed to create the code cache: %s\n", strerror(errno));
return false;
diff --git a/vm/compiler/Compiler.h b/vm/compiler/Compiler.h
index 3b7ae54..47de33d 100644
--- a/vm/compiler/Compiler.h
+++ b/vm/compiler/Compiler.h
@@ -62,8 +62,23 @@
kJitTSelectEnd = 5, // Done with the trace - wrap it up
kJitSingleStep = 6, // Single step interpretation
kJitSingleStepEnd = 7, // Done with single step, return to mterp
+ kJitSelfVerification = 8, // Self Verification Mode
} JitState;
+#if defined(WITH_SELF_VERIFICATION)
+typedef enum SelfVerificationState {
+ kSVSIdle = 0, // Idle
+ kSVSStart = 1, // Shadow space set up, running compiled code
+ kSVSPunt = 2, // Exiting compiled code by punting
+ kSVSSingleStep = 3, // Exiting compiled code by single stepping
+ kSVSTraceSelect = 4, // Exiting compiled code by trace select
+ kSVSNormal = 5, // Exiting compiled code normally
+ kSVSNoChain = 6, // Exiting compiled code by no chain
+ kSVSBackwardBranch = 7, // Exiting compiled code with backward branch trace
+ kSVSDebugInterp = 8, // Normal state restored, running debug interpreter
+} SelfVerificationState;
+#endif
+
typedef enum JitHint {
kJitHintNone = 0,
kJitHintTaken = 1, // Last inst in run was taken branch
@@ -122,4 +137,26 @@
void dvmJitUnchainAll(void);
void dvmCompilerSortAndPrintTraceProfiles(void);
+struct CompilationUnit;
+struct BasicBlock;
+struct SSARepresentation;
+struct GrowableList;
+
+void dvmInitializeSSAConversion(struct CompilationUnit *cUnit);
+int dvmConvertSSARegToDalvik(struct CompilationUnit *cUnit, int ssaReg);
+void dvmCompilerLoopOpt(struct CompilationUnit *cUnit);
+void dvmCompilerNonLoopAnalysis(struct CompilationUnit *cUnit);
+void dvmCompilerFindLiveIn(struct CompilationUnit *cUnit,
+ struct BasicBlock *bb);
+void dvmCompilerDoSSAConversion(struct CompilationUnit *cUnit,
+ struct BasicBlock *bb);
+void dvmCompilerDoConstantPropagation(struct CompilationUnit *cUnit,
+ struct BasicBlock *bb);
+void dvmCompilerFindInductionVariables(struct CompilationUnit *cUnit,
+ struct BasicBlock *bb);
+char *dvmCompilerGetSSAString(struct CompilationUnit *cUnit,
+ struct SSARepresentation *ssaRep);
+void dvmCompilerDataFlowAnalysisDispatcher(struct CompilationUnit *cUnit,
+ void (*func)(struct CompilationUnit *, struct BasicBlock *));
+
#endif /* _DALVIK_VM_COMPILER */
diff --git a/vm/compiler/CompilerIR.h b/vm/compiler/CompilerIR.h
index d61d2ee..d5f60b6 100644
--- a/vm/compiler/CompilerIR.h
+++ b/vm/compiler/CompilerIR.h
@@ -14,19 +14,22 @@
* limitations under the License.
*/
-#include "codegen/Optimizer.h"
-
#ifndef _DALVIK_VM_COMPILER_IR
#define _DALVIK_VM_COMPILER_IR
+#include "codegen/Optimizer.h"
+
typedef enum BBType {
/* For coding convenience reasons chaining cell types should appear first */
CHAINING_CELL_NORMAL = 0,
CHAINING_CELL_HOT,
CHAINING_CELL_INVOKE_SINGLETON,
CHAINING_CELL_INVOKE_PREDICTED,
+ CHAINING_CELL_BACKWARD_BRANCH,
CHAINING_CELL_LAST,
+ ENTRY_BLOCK,
DALVIK_BYTECODE,
+ EXIT_BLOCK,
PC_RECONSTRUCTION,
EXCEPTION_HANDLING,
} BBType;
@@ -45,14 +48,42 @@
struct LIR *target;
} LIR;
+enum ExtendedMIROpcode {
+ MIR_OP_FIRST = 256,
+ MIR_OP_PHI = MIR_OP_FIRST,
+ MIR_OP_NULL_N_RANGE_UP_CHECK,
+ MIR_OP_NULL_N_RANGE_DOWN_CHECK,
+ MIR_OP_LOWER_BOUND_CHECK,
+ MIR_OP_PUNT,
+ MIR_OP_LAST,
+};
+
+struct SSARepresentation;
+
+typedef enum {
+ kMIRIgnoreNullCheck = 0,
+ kMIRNullCheckOnly,
+ kMIRIgnoreRangeCheck,
+ kMIRRangeCheckOnly,
+} MIROptimizationFlagPositons;
+
+#define MIR_IGNORE_NULL_CHECK (1 << kMIRIgnoreNullCheck)
+#define MIR_NULL_CHECK_ONLY (1 << kMIRNullCheckOnly)
+#define MIR_IGNORE_RANGE_CHECK (1 << kMIRIgnoreRangeCheck)
+#define MIR_RANGE_CHECK_ONLY (1 << kMIRRangeCheckOnly)
+
typedef struct MIR {
DecodedInstruction dalvikInsn;
unsigned int width;
unsigned int offset;
struct MIR *prev;
struct MIR *next;
+ struct SSARepresentation *ssaRep;
+ int OptimizationFlags;
} MIR;
+struct BasicBlockDataFlow;
+
typedef struct BasicBlock {
int id;
int visited;
@@ -65,8 +96,11 @@
struct BasicBlock *fallThrough;
struct BasicBlock *taken;
struct BasicBlock *next; // Serial link for book keeping purposes
+ struct BasicBlockDataFlow *dataFlowInfo;
} BasicBlock;
+struct LoopAnalysis;
+
typedef struct CompilationUnit {
int numInsts;
int numBlocks;
@@ -87,21 +121,39 @@
bool allSingleStep;
bool halveInstCount;
bool executionCount; // Add code to count trace executions
+ bool hasLoop;
int numChainingCells[CHAINING_CELL_LAST];
LIR *firstChainingLIR[CHAINING_CELL_LAST];
RegisterScoreboard registerScoreboard; // Track register dependency
int optRound; // round number to tell an LIR's age
JitInstructionSetType instructionSet;
+ /* Number of total regs used in the whole cUnit after SSA transformation */
+ int numSSARegs;
+ /* Map SSA reg i to the Dalvik[15..0]/Sub[31..16] pair. */
+ GrowableList *ssaToDalvikMap;
+
+ /* The following are new data structures to support SSA representations */
+ /* Map original Dalvik reg i to the SSA[15..0]/Sub[31..16] pair */
+ int *dalvikToSSAMap; // length == method->registersSize
+ BitVector *isConstantV; // length == numSSAReg
+ int *constantValues; // length == numSSAReg
+
+ /* Data structure for loop analysis and optimizations */
+ struct LoopAnalysis *loopAnalysis;
} CompilationUnit;
BasicBlock *dvmCompilerNewBB(BBType blockType);
void dvmCompilerAppendMIR(BasicBlock *bb, MIR *mir);
+void dvmCompilerPrependMIR(BasicBlock *bb, MIR *mir);
+
void dvmCompilerAppendLIR(CompilationUnit *cUnit, LIR *lir);
void dvmCompilerInsertLIRBefore(LIR *currentLIR, LIR *newLIR);
+void dvmCompilerInsertLIRAfter(LIR *currentLIR, LIR *newLIR);
+
/* Debug Utilities */
void dvmCompilerDumpCompilationUnit(CompilationUnit *cUnit);
diff --git a/vm/compiler/CompilerInternals.h b/vm/compiler/CompilerInternals.h
index 410213a..9a30b34 100644
--- a/vm/compiler/CompilerInternals.h
+++ b/vm/compiler/CompilerInternals.h
@@ -19,7 +19,6 @@
#include "Dalvik.h"
#include "CompilerUtility.h"
-#include "CompilerIR.h"
#include "codegen/CompilerCodegen.h"
#include "interp/Jit.h"
diff --git a/vm/compiler/CompilerUtility.h b/vm/compiler/CompilerUtility.h
index 7b4de11..409de29 100644
--- a/vm/compiler/CompilerUtility.h
+++ b/vm/compiler/CompilerUtility.h
@@ -38,7 +38,16 @@
void **elemList;
} GrowableList;
+#define GET_ELEM_N(LIST, TYPE, N) (((TYPE*) LIST->elemList)[N])
+
+struct LIR;
+
void dvmInitGrowableList(GrowableList *gList, size_t initLength);
void dvmInsertGrowableList(GrowableList *gList, void *elem);
+BitVector* dvmCompilerAllocBitVector(int startBits, bool expandable);
+bool dvmCompilerSetBit(BitVector* pBits, int num);
+void dvmDebugBitVector(char *msg, const BitVector *bv, int length);
+void dvmDumpLIRInsn(struct LIR *lir, unsigned char *baseAddr);
+void dvmDumpResourceMask(struct LIR *lir, u8 mask, const char *prefix);
#endif /* _DALVIK_COMPILER_UTILITY */
diff --git a/vm/compiler/Dataflow.c b/vm/compiler/Dataflow.c
new file mode 100644
index 0000000..9a2e5c0
--- /dev/null
+++ b/vm/compiler/Dataflow.c
@@ -0,0 +1,1394 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#include "Dalvik.h"
+#include "Dataflow.h"
+#include "Loop.h"
+
+/*
+ * Main table containing data flow attributes for each bytecode. The first
+ * 256 entries are for Dalvik bytecode instructions, where extended opcode at
+ * the MIR level are appended afterwards.
+ *
+ * TODO - many optimization flags are incomplete - they will only limit the
+ * scope of optimizations but will not cause mis-optimizations.
+ */
+int dvmCompilerDataFlowAttributes[MIR_OP_LAST] = {
+ // 00 OP_NOP
+ DF_NOP,
+
+ // 01 OP_MOVE vA, vB
+ DF_DA | DF_UB | DF_IS_MOVE,
+
+ // 02 OP_MOVE_FROM16 vAA, vBBBB
+ DF_DA | DF_UB | DF_IS_MOVE,
+
+ // 03 OP_MOVE_16 vAAAA, vBBBB
+ DF_DA | DF_UB | DF_IS_MOVE,
+
+ // 04 OP_MOVE_WIDE vA, vB
+ DF_DA_WIDE | DF_UB_WIDE | DF_IS_MOVE,
+
+ // 05 OP_MOVE_WIDE_FROM16 vAA, vBBBB
+ DF_DA_WIDE | DF_UB_WIDE | DF_IS_MOVE,
+
+ // 06 OP_MOVE_WIDE_16 vAAAA, vBBBB
+ DF_DA_WIDE | DF_UB_WIDE | DF_IS_MOVE,
+
+ // 07 OP_MOVE_OBJECT vA, vB
+ DF_DA | DF_UB | DF_IS_MOVE,
+
+ // 08 OP_MOVE_OBJECT_FROM16 vAA, vBBBB
+ DF_DA | DF_UB | DF_IS_MOVE,
+
+ // 09 OP_MOVE_OBJECT_16 vAAAA, vBBBB
+ DF_DA | DF_UB | DF_IS_MOVE,
+
+ // 0A OP_MOVE_RESULT vAA
+ DF_DA,
+
+ // 0B OP_MOVE_RESULT_WIDE vAA
+ DF_DA_WIDE,
+
+ // 0C OP_MOVE_RESULT_OBJECT vAA
+ DF_DA,
+
+ // 0D OP_MOVE_EXCEPTION vAA
+ DF_DA,
+
+ // 0E OP_RETURN_VOID
+ DF_NOP,
+
+ // 0F OP_RETURN vAA
+ DF_UA,
+
+ // 10 OP_RETURN_WIDE vAA
+ DF_UA_WIDE,
+
+ // 11 OP_RETURN_OBJECT vAA
+ DF_UA,
+
+ // 12 OP_CONST_4 vA, #+B
+ DF_DA | DF_SETS_CONST,
+
+ // 13 OP_CONST_16 vAA, #+BBBB
+ DF_DA | DF_SETS_CONST,
+
+ // 14 OP_CONST vAA, #+BBBBBBBB
+ DF_DA | DF_SETS_CONST,
+
+ // 15 OP_CONST_HIGH16 VAA, #+BBBB0000
+ DF_DA | DF_SETS_CONST,
+
+ // 16 OP_CONST_WIDE_16 vAA, #+BBBB
+ DF_DA_WIDE | DF_SETS_CONST,
+
+ // 17 OP_CONST_WIDE_32 vAA, #+BBBBBBBB
+ DF_DA_WIDE | DF_SETS_CONST,
+
+ // 18 OP_CONST_WIDE vAA, #+BBBBBBBBBBBBBBBB
+ DF_DA_WIDE | DF_SETS_CONST,
+
+ // 19 OP_CONST_WIDE_HIGH16 vAA, #+BBBB000000000000
+ DF_DA_WIDE | DF_SETS_CONST,
+
+ // 1A OP_CONST_STRING vAA, string@BBBB
+ DF_DA,
+
+ // 1B OP_CONST_STRING_JUMBO vAA, string@BBBBBBBB
+ DF_DA,
+
+ // 1C OP_CONST_CLASS vAA, type@BBBB
+ DF_DA,
+
+ // 1D OP_MONITOR_ENTER vAA
+ DF_UA,
+
+ // 1E OP_MONITOR_EXIT vAA
+ DF_UA,
+
+ // 1F OP_CHECK_CAST vAA, type@BBBB
+ DF_UA,
+
+ // 20 OP_INSTANCE_OF vA, vB, type@CCCC
+ DF_DA | DF_UB,
+
+ // 21 OP_ARRAY_LENGTH vA, vB
+ DF_DA | DF_UB,
+
+ // 22 OP_NEW_INSTANCE vAA, type@BBBB
+ DF_DA,
+
+ // 23 OP_NEW_ARRAY vA, vB, type@CCCC
+ DF_DA | DF_UB,
+
+ // 24 OP_FILLED_NEW_ARRAY {vD, vE, vF, vG, vA}
+ DF_FORMAT_35C,
+
+ // 25 OP_FILLED_NEW_ARRAY_RANGE {vCCCC .. vNNNN}, type@BBBB
+ DF_FORMAT_3RC,
+
+ // 26 OP_FILL_ARRAY_DATA vAA, +BBBBBBBB
+ DF_UA,
+
+ // 27 OP_THROW vAA
+ DF_UA,
+
+ // 28 OP_GOTO
+ DF_NOP,
+
+ // 29 OP_GOTO_16
+ DF_NOP,
+
+ // 2A OP_GOTO_32
+ DF_NOP,
+
+ // 2B OP_PACKED_SWITCH vAA, +BBBBBBBB
+ DF_UA,
+
+ // 2C OP_SPARSE_SWITCH vAA, +BBBBBBBB
+ DF_UA,
+
+ // 2D OP_CMPL_FLOAT vAA, vBB, vCC
+ DF_DA | DF_UB | DF_UC,
+
+ // 2E OP_CMPG_FLOAT vAA, vBB, vCC
+ DF_DA | DF_UB | DF_UC,
+
+ // 2F OP_CMPL_DOUBLE vAA, vBB, vCC
+ DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+ // 30 OP_CMPG_DOUBLE vAA, vBB, vCC
+ DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+ // 31 OP_CMP_LONG vAA, vBB, vCC
+ DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+ // 32 OP_IF_EQ vA, vB, +CCCC
+ DF_UA | DF_UB,
+
+ // 33 OP_IF_NE vA, vB, +CCCC
+ DF_UA | DF_UB,
+
+ // 34 OP_IF_LT vA, vB, +CCCC
+ DF_UA | DF_UB,
+
+ // 35 OP_IF_GE vA, vB, +CCCC
+ DF_UA | DF_UB,
+
+ // 36 OP_IF_GT vA, vB, +CCCC
+ DF_UA | DF_UB,
+
+ // 37 OP_IF_LE vA, vB, +CCCC
+ DF_UA | DF_UB,
+
+
+ // 38 OP_IF_EQZ vAA, +BBBB
+ DF_UA,
+
+ // 39 OP_IF_NEZ vAA, +BBBB
+ DF_UA,
+
+ // 3A OP_IF_LTZ vAA, +BBBB
+ DF_UA,
+
+ // 3B OP_IF_GEZ vAA, +BBBB
+ DF_UA,
+
+ // 3C OP_IF_GTZ vAA, +BBBB
+ DF_UA,
+
+ // 3D OP_IF_LEZ vAA, +BBBB
+ DF_UA,
+
+ // 3E OP_UNUSED_3E
+ DF_NOP,
+
+ // 3F OP_UNUSED_3F
+ DF_NOP,
+
+ // 40 OP_UNUSED_40
+ DF_NOP,
+
+ // 41 OP_UNUSED_41
+ DF_NOP,
+
+ // 42 OP_UNUSED_42
+ DF_NOP,
+
+ // 43 OP_UNUSED_43
+ DF_NOP,
+
+ // 44 OP_AGET vAA, vBB, vCC
+ DF_DA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_0,
+
+ // 45 OP_AGET_WIDE vAA, vBB, vCC
+ DF_DA_WIDE | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_0,
+
+ // 46 OP_AGET_OBJECT vAA, vBB, vCC
+ DF_DA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_0,
+
+ // 47 OP_AGET_BOOLEAN vAA, vBB, vCC
+ DF_DA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_0,
+
+ // 48 OP_AGET_BYTE vAA, vBB, vCC
+ DF_DA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_0,
+
+ // 49 OP_AGET_CHAR vAA, vBB, vCC
+ DF_DA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_0,
+
+ // 4A OP_AGET_SHORT vAA, vBB, vCC
+ DF_DA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_0,
+
+ // 4B OP_APUT vAA, vBB, vCC
+ DF_UA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_1,
+
+ // 4C OP_APUT_WIDE vAA, vBB, vCC
+ DF_UA_WIDE | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_2,
+
+ // 4D OP_APUT_OBJECT vAA, vBB, vCC
+ DF_UA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_1,
+
+ // 4E OP_APUT_BOOLEAN vAA, vBB, vCC
+ DF_UA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_1,
+
+ // 4F OP_APUT_BYTE vAA, vBB, vCC
+ DF_UA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_1,
+
+ // 50 OP_APUT_CHAR vAA, vBB, vCC
+ DF_UA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_1,
+
+ // 51 OP_APUT_SHORT vAA, vBB, vCC
+ DF_UA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_1,
+
+ // 52 OP_IGET vA, vB, field@CCCC
+ DF_DA | DF_UB,
+
+ // 53 OP_IGET_WIDE vA, vB, field@CCCC
+ DF_DA_WIDE | DF_UB,
+
+ // 54 OP_IGET_OBJECT vA, vB, field@CCCC
+ DF_DA | DF_UB,
+
+ // 55 OP_IGET_BOOLEAN vA, vB, field@CCCC
+ DF_DA | DF_UB,
+
+ // 56 OP_IGET_BYTE vA, vB, field@CCCC
+ DF_DA | DF_UB,
+
+ // 57 OP_IGET_CHAR vA, vB, field@CCCC
+ DF_DA | DF_UB,
+
+ // 58 OP_IGET_SHORT vA, vB, field@CCCC
+ DF_DA | DF_UB,
+
+ // 59 OP_IPUT vA, vB, field@CCCC
+ DF_UA | DF_UB,
+
+ // 5A OP_IPUT_WIDE vA, vB, field@CCCC
+ DF_UA_WIDE | DF_UB,
+
+ // 5B OP_IPUT_OBJECT vA, vB, field@CCCC
+ DF_UA | DF_UB,
+
+ // 5C OP_IPUT_BOOLEAN vA, vB, field@CCCC
+ DF_UA | DF_UB,
+
+ // 5D OP_IPUT_BYTE vA, vB, field@CCCC
+ DF_UA | DF_UB,
+
+ // 5E OP_IPUT_CHAR vA, vB, field@CCCC
+ DF_UA | DF_UB,
+
+ // 5F OP_IPUT_SHORT vA, vB, field@CCCC
+ DF_UA | DF_UB,
+
+ // 60 OP_SGET vAA, field@BBBB
+ DF_DA,
+
+ // 61 OP_SGET_WIDE vAA, field@BBBB
+ DF_DA_WIDE,
+
+ // 62 OP_SGET_OBJECT vAA, field@BBBB
+ DF_DA,
+
+ // 63 OP_SGET_BOOLEAN vAA, field@BBBB
+ DF_DA,
+
+ // 64 OP_SGET_BYTE vAA, field@BBBB
+ DF_DA,
+
+ // 65 OP_SGET_CHAR vAA, field@BBBB
+ DF_DA,
+
+ // 66 OP_SGET_SHORT vAA, field@BBBB
+ DF_DA,
+
+ // 67 OP_SPUT vAA, field@BBBB
+ DF_UA,
+
+ // 68 OP_SPUT_WIDE vAA, field@BBBB
+ DF_UA_WIDE,
+
+ // 69 OP_SPUT_OBJECT vAA, field@BBBB
+ DF_UA,
+
+ // 6A OP_SPUT_BOOLEAN vAA, field@BBBB
+ DF_UA,
+
+ // 6B OP_SPUT_BYTE vAA, field@BBBB
+ DF_UA,
+
+ // 6C OP_SPUT_CHAR vAA, field@BBBB
+ DF_UA,
+
+ // 6D OP_SPUT_SHORT vAA, field@BBBB
+ DF_UA,
+
+ // 6E OP_INVOKE_VIRTUAL {vD, vE, vF, vG, vA}
+ DF_FORMAT_35C,
+
+ // 6F OP_INVOKE_SUPER {vD, vE, vF, vG, vA}
+ DF_FORMAT_35C,
+
+ // 70 OP_INVOKE_DIRECT {vD, vE, vF, vG, vA}
+ DF_FORMAT_35C,
+
+ // 71 OP_INVOKE_STATIC {vD, vE, vF, vG, vA}
+ DF_FORMAT_35C,
+
+ // 72 OP_INVOKE_INTERFACE {vD, vE, vF, vG, vA}
+ DF_FORMAT_35C,
+
+ // 73 OP_UNUSED_73
+ DF_NOP,
+
+ // 74 OP_INVOKE_VIRTUAL_RANGE {vCCCC .. vNNNN}
+ DF_FORMAT_3RC,
+
+ // 75 OP_INVOKE_SUPER_RANGE {vCCCC .. vNNNN}
+ DF_FORMAT_3RC,
+
+ // 76 OP_INVOKE_DIRECT_RANGE {vCCCC .. vNNNN}
+ DF_FORMAT_3RC,
+
+ // 77 OP_INVOKE_STATIC_RANGE {vCCCC .. vNNNN}
+ DF_FORMAT_3RC,
+
+ // 78 OP_INVOKE_INTERFACE_RANGE {vCCCC .. vNNNN}
+ DF_FORMAT_3RC,
+
+ // 79 OP_UNUSED_79
+ DF_NOP,
+
+ // 7A OP_UNUSED_7A
+ DF_NOP,
+
+ // 7B OP_NEG_INT vA, vB
+ DF_DA | DF_UB,
+
+ // 7C OP_NOT_INT vA, vB
+ DF_DA | DF_UB,
+
+ // 7D OP_NEG_LONG vA, vB
+ DF_DA_WIDE | DF_UB_WIDE,
+
+ // 7E OP_NOT_LONG vA, vB
+ DF_DA_WIDE | DF_UB_WIDE,
+
+ // 7F OP_NEG_FLOAT vA, vB
+ DF_DA | DF_UB,
+
+ // 80 OP_NEG_DOUBLE vA, vB
+ DF_DA_WIDE | DF_UB_WIDE,
+
+ // 81 OP_INT_TO_LONG vA, vB
+ DF_DA_WIDE | DF_UB,
+
+ // 82 OP_INT_TO_FLOAT vA, vB
+ DF_DA | DF_UB,
+
+ // 83 OP_INT_TO_DOUBLE vA, vB
+ DF_DA_WIDE | DF_UB,
+
+ // 84 OP_LONG_TO_INT vA, vB
+ DF_DA | DF_UB_WIDE,
+
+ // 85 OP_LONG_TO_FLOAT vA, vB
+ DF_DA | DF_UB_WIDE,
+
+ // 86 OP_LONG_TO_DOUBLE vA, vB
+ DF_DA_WIDE | DF_UB_WIDE,
+
+ // 87 OP_FLOAT_TO_INT vA, vB
+ DF_DA | DF_UB,
+
+ // 88 OP_FLOAT_TO_LONG vA, vB
+ DF_DA_WIDE | DF_UB,
+
+ // 89 OP_FLOAT_TO_DOUBLE vA, vB
+ DF_DA_WIDE | DF_UB,
+
+ // 8A OP_DOUBLE_TO_INT vA, vB
+ DF_DA | DF_UB_WIDE,
+
+ // 8B OP_DOUBLE_TO_LONG vA, vB
+ DF_DA_WIDE | DF_UB_WIDE,
+
+ // 8C OP_DOUBLE_TO_FLOAT vA, vB
+ DF_DA | DF_UB_WIDE,
+
+ // 8D OP_INT_TO_BYTE vA, vB
+ DF_DA | DF_UB,
+
+ // 8E OP_INT_TO_CHAR vA, vB
+ DF_DA | DF_UB,
+
+ // 8F OP_INT_TO_SHORT vA, vB
+ DF_DA | DF_UB,
+
+ // 90 OP_ADD_INT vAA, vBB, vCC
+ DF_DA | DF_UB | DF_UC | DF_IS_LINEAR,
+
+ // 91 OP_SUB_INT vAA, vBB, vCC
+ DF_DA | DF_UB | DF_UC | DF_IS_LINEAR,
+
+ // 92 OP_MUL_INT vAA, vBB, vCC
+ DF_DA | DF_UB | DF_UC,
+
+ // 93 OP_DIV_INT vAA, vBB, vCC
+ DF_DA | DF_UB | DF_UC,
+
+ // 94 OP_REM_INT vAA, vBB, vCC
+ DF_DA | DF_UB | DF_UC,
+
+ // 95 OP_AND_INT vAA, vBB, vCC
+ DF_DA | DF_UB | DF_UC,
+
+ // 96 OP_OR_INT vAA, vBB, vCC
+ DF_DA | DF_UB | DF_UC,
+
+ // 97 OP_XOR_INT vAA, vBB, vCC
+ DF_DA | DF_UB | DF_UC,
+
+ // 98 OP_SHL_INT vAA, vBB, vCC
+ DF_DA | DF_UB | DF_UC,
+
+ // 99 OP_SHR_INT vAA, vBB, vCC
+ DF_DA | DF_UB | DF_UC,
+
+ // 9A OP_USHR_INT vAA, vBB, vCC
+ DF_DA | DF_UB | DF_UC,
+
+ // 9B OP_ADD_LONG vAA, vBB, vCC
+ DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+ // 9C OP_SUB_LONG vAA, vBB, vCC
+ DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+ // 9D OP_MUL_LONG vAA, vBB, vCC
+ DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+ // 9E OP_DIV_LONG vAA, vBB, vCC
+ DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+ // 9F OP_REM_LONG vAA, vBB, vCC
+ DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+ // A0 OP_AND_LONG vAA, vBB, vCC
+ DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+ // A1 OP_OR_LONG vAA, vBB, vCC
+ DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+ // A2 OP_XOR_LONG vAA, vBB, vCC
+ DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+ // A3 OP_SHL_LONG vAA, vBB, vCC
+ DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+ // A4 OP_SHR_LONG vAA, vBB, vCC
+ DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+ // A5 OP_USHR_LONG vAA, vBB, vCC
+ DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+ // A6 OP_ADD_FLOAT vAA, vBB, vCC
+ DF_DA | DF_UB | DF_UC,
+
+ // A7 OP_SUB_FLOAT vAA, vBB, vCC
+ DF_DA | DF_UB | DF_UC,
+
+ // A8 OP_MUL_FLOAT vAA, vBB, vCC
+ DF_DA | DF_UB | DF_UC,
+
+ // A9 OP_DIV_FLOAT vAA, vBB, vCC
+ DF_DA | DF_UB | DF_UC,
+
+ // AA OP_REM_FLOAT vAA, vBB, vCC
+ DF_DA | DF_UB | DF_UC,
+
+ // AB OP_ADD_DOUBLE vAA, vBB, vCC
+ DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+ // AC OP_SUB_DOUBLE vAA, vBB, vCC
+ DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+ // AD OP_MUL_DOUBLE vAA, vBB, vCC
+ DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+ // AE OP_DIV_DOUBLE vAA, vBB, vCC
+ DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+ // AF OP_REM_DOUBLE vAA, vBB, vCC
+ DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
+
+ // B0 OP_ADD_INT_2ADDR vA, vB
+ DF_DA | DF_UA | DF_UB,
+
+ // B1 OP_SUB_INT_2ADDR vA, vB
+ DF_DA | DF_UA | DF_UB,
+
+ // B2 OP_MUL_INT_2ADDR vA, vB
+ DF_DA | DF_UA | DF_UB,
+
+ // B3 OP_DIV_INT_2ADDR vA, vB
+ DF_DA | DF_UA | DF_UB,
+
+ // B4 OP_REM_INT_2ADDR vA, vB
+ DF_DA | DF_UA | DF_UB,
+
+ // B5 OP_AND_INT_2ADDR vA, vB
+ DF_DA | DF_UA | DF_UB,
+
+ // B6 OP_OR_INT_2ADDR vA, vB
+ DF_DA | DF_UA | DF_UB,
+
+ // B7 OP_XOR_INT_2ADDR vA, vB
+ DF_DA | DF_UA | DF_UB,
+
+ // B8 OP_SHL_INT_2ADDR vA, vB
+ DF_DA | DF_UA | DF_UB,
+
+ // B9 OP_SHR_INT_2ADDR vA, vB
+ DF_DA | DF_UA | DF_UB,
+
+ // BA OP_USHR_INT_2ADDR vA, vB
+ DF_DA | DF_UA | DF_UB,
+
+ // BB OP_ADD_LONG_2ADDR vA, vB
+ DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+ // BC OP_SUB_LONG_2ADDR vA, vB
+ DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+ // BD OP_MUL_LONG_2ADDR vA, vB
+ DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+ // BE OP_DIV_LONG_2ADDR vA, vB
+ DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+ // BF OP_REM_LONG_2ADDR vA, vB
+ DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+ // C0 OP_AND_LONG_2ADDR vA, vB
+ DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+ // C1 OP_OR_LONG_2ADDR vA, vB
+ DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+ // C2 OP_XOR_LONG_2ADDR vA, vB
+ DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+ // C3 OP_SHL_LONG_2ADDR vA, vB
+ DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+ // C4 OP_SHR_LONG_2ADDR vA, vB
+ DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+ // C5 OP_USHR_LONG_2ADDR vA, vB
+ DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+ // C6 OP_ADD_FLOAT_2ADDR vA, vB
+ DF_DA | DF_UA | DF_UB,
+
+ // C7 OP_SUB_FLOAT_2ADDR vA, vB
+ DF_DA | DF_UA | DF_UB,
+
+ // C8 OP_MUL_FLOAT_2ADDR vA, vB
+ DF_DA | DF_UA | DF_UB,
+
+ // C9 OP_DIV_FLOAT_2ADDR vA, vB
+ DF_DA | DF_UA | DF_UB,
+
+ // CA OP_REM_FLOAT_2ADDR vA, vB
+ DF_DA | DF_UA | DF_UB,
+
+ // CB OP_ADD_DOUBLE_2ADDR vA, vB
+ DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+ // CC OP_SUB_DOUBLE_2ADDR vA, vB
+ DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+ // CD OP_MUL_DOUBLE_2ADDR vA, vB
+ DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+ // CE OP_DIV_DOUBLE_2ADDR vA, vB
+ DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+ // CF OP_REM_DOUBLE_2ADDR vA, vB
+ DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
+
+ // D0 OP_ADD_INT_LIT16 vA, vB, #+CCCC
+ DF_DA | DF_UB,
+
+ // D1 OP_RSUB_INT vA, vB, #+CCCC
+ DF_DA | DF_UB,
+
+ // D2 OP_MUL_INT_LIT16 vA, vB, #+CCCC
+ DF_DA | DF_UB,
+
+ // D3 OP_DIV_INT_LIT16 vA, vB, #+CCCC
+ DF_DA | DF_UB,
+
+ // D4 OP_REM_INT_LIT16 vA, vB, #+CCCC
+ DF_DA | DF_UB,
+
+ // D5 OP_AND_INT_LIT16 vA, vB, #+CCCC
+ DF_DA | DF_UB,
+
+ // D6 OP_OR_INT_LIT16 vA, vB, #+CCCC
+ DF_DA | DF_UB,
+
+ // D7 OP_XOR_INT_LIT16 vA, vB, #+CCCC
+ DF_DA | DF_UB,
+
+ // D8 OP_ADD_INT_LIT8 vAA, vBB, #+CC
+ DF_DA | DF_UB | DF_IS_LINEAR,
+
+ // D9 OP_RSUB_INT_LIT8 vAA, vBB, #+CC
+ DF_DA | DF_UB,
+
+ // DA OP_MUL_INT_LIT8 vAA, vBB, #+CC
+ DF_DA | DF_UB,
+
+ // DB OP_DIV_INT_LIT8 vAA, vBB, #+CC
+ DF_DA | DF_UB,
+
+ // DC OP_REM_INT_LIT8 vAA, vBB, #+CC
+ DF_DA | DF_UB,
+
+ // DD OP_AND_INT_LIT8 vAA, vBB, #+CC
+ DF_DA | DF_UB,
+
+ // DE OP_OR_INT_LIT8 vAA, vBB, #+CC
+ DF_DA | DF_UB,
+
+ // DF OP_XOR_INT_LIT8 vAA, vBB, #+CC
+ DF_DA | DF_UB,
+
+ // E0 OP_SHL_INT_LIT8 vAA, vBB, #+CC
+ DF_DA | DF_UB,
+
+ // E1 OP_SHR_INT_LIT8 vAA, vBB, #+CC
+ DF_DA | DF_UB,
+
+ // E2 OP_USHR_INT_LIT8 vAA, vBB, #+CC
+ DF_DA | DF_UB,
+
+ // E3 OP_UNUSED_E3
+ DF_NOP,
+
+ // E4 OP_UNUSED_E4
+ DF_NOP,
+
+ // E5 OP_UNUSED_E5
+ DF_NOP,
+
+ // E6 OP_UNUSED_E6
+ DF_NOP,
+
+ // E7 OP_UNUSED_E7
+ DF_NOP,
+
+ // E8 OP_UNUSED_E8
+ DF_NOP,
+
+ // E9 OP_UNUSED_E9
+ DF_NOP,
+
+ // EA OP_UNUSED_EA
+ DF_NOP,
+
+ // EB OP_UNUSED_EB
+ DF_NOP,
+
+ // EC OP_UNUSED_EC
+ DF_NOP,
+
+ // ED OP_THROW_VERIFICATION_ERROR
+ DF_NOP,
+
+ // EE OP_EXECUTE_INLINE
+ DF_FORMAT_35C,
+
+ // EF OP_UNUSED_EF
+ DF_NOP,
+
+ // F0 OP_INVOKE_DIRECT_EMPTY
+ DF_NOP,
+
+ // F1 OP_UNUSED_F1
+ DF_NOP,
+
+ // F2 OP_IGET_QUICK
+ DF_DA | DF_UB,
+
+ // F3 OP_IGET_WIDE_QUICK
+ DF_DA_WIDE | DF_UB,
+
+ // F4 OP_IGET_OBJECT_QUICK
+ DF_DA | DF_UB,
+
+ // F5 OP_IPUT_QUICK
+ DF_UA | DF_UB,
+
+ // F6 OP_IPUT_WIDE_QUICK
+ DF_UA_WIDE | DF_UB,
+
+ // F7 OP_IPUT_OBJECT_QUICK
+ DF_UA | DF_UB,
+
+ // F8 OP_INVOKE_VIRTUAL_QUICK
+ DF_FORMAT_35C,
+
+ // F9 OP_INVOKE_VIRTUAL_QUICK_RANGE
+ DF_FORMAT_3RC,
+
+ // FA OP_INVOKE_SUPER_QUICK
+ DF_FORMAT_35C,
+
+ // FB OP_INVOKE_SUPER_QUICK_RANGE
+ DF_FORMAT_3RC,
+
+ // FC OP_UNUSED_FC
+ DF_NOP,
+
+ // FD OP_UNUSED_FD
+ DF_NOP,
+
+ // FE OP_UNUSED_FE
+ DF_NOP,
+
+ // FF OP_UNUSED_FF
+ DF_NOP,
+
+ // Beginning of extended MIR opcodes
+ // 100 OP_MIR_PHI
+ DF_PHI | DF_DA,
+
+ /*
+ * For extended MIR inserted at the MIR2LIR stage, it is okay to have
+ * undefined values here.
+ */
+};
+
+/* Return the Dalvik register/subscript pair of a given SSA register */
+int dvmConvertSSARegToDalvik(CompilationUnit *cUnit, int ssaReg)
+{
+ return GET_ELEM_N(cUnit->ssaToDalvikMap, int, ssaReg);
+}
+
+/*
+ * Utility function to convert encoded SSA register value into Dalvik register
+ * and subscript pair. Each SSA register can be used to index the
+ * ssaToDalvikMap list to get the subscript[31..16]/dalvik_reg[15..0] mapping.
+ */
+char *dvmCompilerGetSSAString(CompilationUnit *cUnit, SSARepresentation *ssaRep)
+{
+ char buffer[256];
+ char *ret;
+ int i;
+
+ buffer[0] = 0;
+ for (i = 0; i < ssaRep->numDefs; i++) {
+ int ssa2DalvikValue = dvmConvertSSARegToDalvik(cUnit, ssaRep->defs[i]);
+
+ sprintf(buffer + strlen(buffer), "s%d(v%d_%d) ",
+ ssaRep->defs[i], DECODE_REG(ssa2DalvikValue),
+ DECODE_SUB(ssa2DalvikValue));
+ }
+
+ if (ssaRep->numDefs) {
+ strcat(buffer, "<- ");
+ }
+
+ for (i = 0; i < ssaRep->numUses; i++) {
+ int ssa2DalvikValue = dvmConvertSSARegToDalvik(cUnit, ssaRep->uses[i]);
+ int len = strlen(buffer);
+
+ if (snprintf(buffer + len, 250 - len, "s%d(v%d_%d) ",
+ ssaRep->uses[i], DECODE_REG(ssa2DalvikValue),
+ DECODE_SUB(ssa2DalvikValue)) >= (250 - len)) {
+ strcat(buffer, "...");
+ break;
+ }
+ }
+
+ int length = strlen(buffer) + 1;
+ ret = dvmCompilerNew(length, false);
+ memcpy(ret, buffer, length);
+ return ret;
+}
+
+/* Any register that is used before being defined is considered live-in */
+static inline void handleLiveInUse(BitVector *useV, BitVector *defV,
+ BitVector *liveInV, int dalvikRegId)
+{
+ dvmCompilerSetBit(useV, dalvikRegId);
+ if (!dvmIsBitSet(defV, dalvikRegId)) {
+ dvmCompilerSetBit(liveInV, dalvikRegId);
+ }
+}
+
+/* Mark a reg as being defined */
+static inline void handleLiveInDef(BitVector *defV, int dalvikRegId)
+{
+ dvmCompilerSetBit(defV, dalvikRegId);
+}
+
+/*
+ * Find out live-in variables for natural loops. Variables that are live-in in
+ * the main loop body are considered to be defined in the entry block.
+ */
+void dvmCompilerFindLiveIn(CompilationUnit *cUnit, BasicBlock *bb)
+{
+ MIR *mir;
+ BitVector *useV, *defV, *liveInV;
+
+ if (bb->blockType != DALVIK_BYTECODE &&
+ bb->blockType != ENTRY_BLOCK) {
+ return;
+ }
+
+ useV = bb->dataFlowInfo->useV =
+ dvmCompilerAllocBitVector(cUnit->method->registersSize, false);
+ defV = bb->dataFlowInfo->defV =
+ dvmCompilerAllocBitVector(cUnit->method->registersSize, false);
+ liveInV = bb->dataFlowInfo->liveInV =
+ dvmCompilerAllocBitVector(cUnit->method->registersSize, false);
+
+ for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
+ int dfAttributes =
+ dvmCompilerDataFlowAttributes[mir->dalvikInsn.opCode];
+ DecodedInstruction *dInsn = &mir->dalvikInsn;
+
+ if (dfAttributes & DF_HAS_USES) {
+ if (dfAttributes & DF_UA) {
+ handleLiveInUse(useV, defV, liveInV, dInsn->vA);
+ } else if (dfAttributes & DF_UA_WIDE) {
+ handleLiveInUse(useV, defV, liveInV, dInsn->vA);
+ handleLiveInUse(useV, defV, liveInV, dInsn->vA+1);
+ }
+ if (dfAttributes & DF_UB) {
+ handleLiveInUse(useV, defV, liveInV, dInsn->vB);
+ } else if (dfAttributes & DF_UB_WIDE) {
+ handleLiveInUse(useV, defV, liveInV, dInsn->vB);
+ handleLiveInUse(useV, defV, liveInV, dInsn->vB+1);
+ }
+ if (dfAttributes & DF_UC) {
+ handleLiveInUse(useV, defV, liveInV, dInsn->vC);
+ } else if (dfAttributes & DF_UC_WIDE) {
+ handleLiveInUse(useV, defV, liveInV, dInsn->vC);
+ handleLiveInUse(useV, defV, liveInV, dInsn->vC+1);
+ }
+ }
+ if (dfAttributes & DF_HAS_DEFS) {
+ handleLiveInDef(defV, dInsn->vA);
+ if (dfAttributes & DF_DA_WIDE) {
+ handleLiveInDef(defV, dInsn->vA+1);
+ }
+ }
+ }
+}
+
+/* Find out the latest SSA register for a given Dalvik register */
+static void handleSSAUse(CompilationUnit *cUnit, int *uses, int dalvikReg,
+ int regIndex)
+{
+ int encodedValue = cUnit->dalvikToSSAMap[dalvikReg];
+ int ssaReg = DECODE_REG(encodedValue);
+ uses[regIndex] = ssaReg;
+}
+
+/* Setup a new SSA register for a given Dalvik register */
+static void handleSSADef(CompilationUnit *cUnit, int *defs, int dalvikReg,
+ int regIndex)
+{
+ int encodedValue = cUnit->dalvikToSSAMap[dalvikReg];
+ int ssaReg = cUnit->numSSARegs++;
+ /* Bump up the subscript */
+ int dalvikSub = DECODE_SUB(encodedValue) + 1;
+ int newD2SMapping = ENCODE_REG_SUB(ssaReg, dalvikSub);
+
+ cUnit->dalvikToSSAMap[dalvikReg] = newD2SMapping;
+
+ int newS2DMapping = ENCODE_REG_SUB(dalvikReg, dalvikSub);
+ dvmInsertGrowableList(cUnit->ssaToDalvikMap, (void *) newS2DMapping);
+
+ defs[regIndex] = ssaReg;
+}
+
+/* Loop up new SSA names for format_35c instructions */
+static void dataFlowSSAFormat35C(CompilationUnit *cUnit, MIR *mir)
+{
+ DecodedInstruction *dInsn = &mir->dalvikInsn;
+ int numUses = dInsn->vA;
+ int i;
+
+ mir->ssaRep->numUses = numUses;
+ mir->ssaRep->uses = dvmCompilerNew(sizeof(int) * numUses, false);
+
+ for (i = 0; i < numUses; i++) {
+ handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->arg[i], i);
+ }
+}
+
+/* Loop up new SSA names for format_3rc instructions */
+static void dataFlowSSAFormat3RC(CompilationUnit *cUnit, MIR *mir)
+{
+ DecodedInstruction *dInsn = &mir->dalvikInsn;
+ int numUses = dInsn->vA;
+ int i;
+
+ mir->ssaRep->numUses = numUses;
+ mir->ssaRep->uses = dvmCompilerNew(sizeof(int) * numUses, false);
+
+ for (i = 0; i < numUses; i++) {
+ handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vC+i, i);
+ }
+}
+
+/* Entry function to convert a block into SSA representation */
+void dvmCompilerDoSSAConversion(CompilationUnit *cUnit, BasicBlock *bb)
+{
+ MIR *mir;
+
+ if (bb->blockType != DALVIK_BYTECODE && bb->blockType != ENTRY_BLOCK) {
+ return;
+ }
+
+ for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
+ mir->ssaRep = dvmCompilerNew(sizeof(SSARepresentation), true);
+
+ int dfAttributes =
+ dvmCompilerDataFlowAttributes[mir->dalvikInsn.opCode];
+
+ int numUses = 0;
+
+ if (dfAttributes & DF_FORMAT_35C) {
+ dataFlowSSAFormat35C(cUnit, mir);
+ continue;
+ }
+
+ if (dfAttributes & DF_FORMAT_3RC) {
+ dataFlowSSAFormat3RC(cUnit, mir);
+ continue;
+ }
+
+ if (dfAttributes & DF_HAS_USES) {
+ if (dfAttributes & DF_UA) {
+ numUses++;
+ } else if (dfAttributes & DF_UA_WIDE) {
+ numUses += 2;
+ }
+ if (dfAttributes & DF_UB) {
+ numUses++;
+ } else if (dfAttributes & DF_UB_WIDE) {
+ numUses += 2;
+ }
+ if (dfAttributes & DF_UC) {
+ numUses++;
+ } else if (dfAttributes & DF_UC_WIDE) {
+ numUses += 2;
+ }
+ }
+
+ if (numUses) {
+ mir->ssaRep->numUses = numUses;
+ mir->ssaRep->uses = dvmCompilerNew(sizeof(int) * numUses, false);
+ }
+
+ int numDefs = 0;
+
+ if (dfAttributes & DF_HAS_DEFS) {
+ numDefs++;
+ if (dfAttributes & DF_DA_WIDE) {
+ numDefs++;
+ }
+ }
+
+ if (numDefs) {
+ mir->ssaRep->numDefs = numDefs;
+ mir->ssaRep->defs = dvmCompilerNew(sizeof(int) * numDefs, false);
+ }
+
+ DecodedInstruction *dInsn = &mir->dalvikInsn;
+
+ if (dfAttributes & DF_HAS_USES) {
+ numUses = 0;
+ if (dfAttributes & DF_UA) {
+ handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vA, numUses++);
+ } else if (dfAttributes & DF_UA_WIDE) {
+ handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vA, numUses++);
+ handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vA+1, numUses++);
+ }
+ if (dfAttributes & DF_UB) {
+ handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vB, numUses++);
+ } else if (dfAttributes & DF_UB_WIDE) {
+ handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vB, numUses++);
+ handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vB+1, numUses++);
+ }
+ if (dfAttributes & DF_UC) {
+ handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vC, numUses++);
+ } else if (dfAttributes & DF_UC_WIDE) {
+ handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vC, numUses++);
+ handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vC+1, numUses++);
+ }
+ }
+ if (dfAttributes & DF_HAS_DEFS) {
+ handleSSADef(cUnit, mir->ssaRep->defs, dInsn->vA, 0);
+ if (dfAttributes & DF_DA_WIDE) {
+ handleSSADef(cUnit, mir->ssaRep->defs, dInsn->vA+1, 1);
+ }
+ }
+ }
+
+ bb->dataFlowInfo->dalvikToSSAMap =
+ dvmCompilerNew(sizeof(int) * cUnit->method->registersSize, false);
+
+ /* Take a snapshot of Dalvik->SSA mapping at the end of each block */
+ memcpy(bb->dataFlowInfo->dalvikToSSAMap, cUnit->dalvikToSSAMap,
+ sizeof(int) * cUnit->method->registersSize);
+}
+
+/* Setup a constant value for opcodes thare have the DF_SETS_CONST attribute */
+static void setConstant(CompilationUnit *cUnit, int ssaReg, int value)
+{
+ dvmSetBit(cUnit->isConstantV, ssaReg);
+ cUnit->constantValues[ssaReg] = value;
+}
+
+void dvmCompilerDoConstantPropagation(CompilationUnit *cUnit, BasicBlock *bb)
+{
+ MIR *mir;
+ BitVector *isConstantV = cUnit->isConstantV;
+
+ for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
+ int dfAttributes =
+ dvmCompilerDataFlowAttributes[mir->dalvikInsn.opCode];
+
+ int numUses = 0;
+
+ DecodedInstruction *dInsn = &mir->dalvikInsn;
+
+ if (!(dfAttributes & DF_HAS_DEFS)) continue;
+
+ /* Handle instructions that set up constants directly */
+ if (dfAttributes & DF_SETS_CONST) {
+ if (dfAttributes & DF_DA) {
+ switch (dInsn->opCode) {
+ case OP_CONST_4:
+ case OP_CONST_16:
+ case OP_CONST:
+ setConstant(cUnit, mir->ssaRep->defs[0], dInsn->vB);
+ break;
+ case OP_CONST_HIGH16:
+ setConstant(cUnit, mir->ssaRep->defs[0],
+ dInsn->vB << 16);
+ break;
+ default:
+ break;
+ }
+ } else if (dfAttributes & DF_DA_WIDE) {
+ switch (dInsn->opCode) {
+ case OP_CONST_WIDE_16:
+ case OP_CONST_WIDE_32:
+ setConstant(cUnit, mir->ssaRep->defs[0], dInsn->vB);
+ setConstant(cUnit, mir->ssaRep->defs[1], 0);
+ break;
+ case OP_CONST_WIDE:
+ setConstant(cUnit, mir->ssaRep->defs[0],
+ (int) dInsn->vB_wide);
+ setConstant(cUnit, mir->ssaRep->defs[1],
+ (int) (dInsn->vB_wide >> 32));
+ break;
+ case OP_CONST_WIDE_HIGH16:
+ setConstant(cUnit, mir->ssaRep->defs[0], 0);
+ setConstant(cUnit, mir->ssaRep->defs[1],
+ dInsn->vB << 16);
+ break;
+ default:
+ break;
+ }
+ }
+ /* Handle instructions that set up constants directly */
+ } else if (dfAttributes & DF_IS_MOVE) {
+ int i;
+
+ for (i = 0; i < mir->ssaRep->numUses; i++) {
+ if (!dvmIsBitSet(isConstantV, mir->ssaRep->uses[i])) break;
+ }
+ /* Move a register holding a constant to another register */
+ if (i == mir->ssaRep->numUses) {
+ setConstant(cUnit, mir->ssaRep->defs[0],
+ cUnit->constantValues[mir->ssaRep->uses[0]]);
+ if (dfAttributes & DF_DA_WIDE) {
+ setConstant(cUnit, mir->ssaRep->defs[1],
+ cUnit->constantValues[mir->ssaRep->uses[1]]);
+ }
+ }
+ }
+ }
+ /* TODO: implement code to handle arithmetic operations */
+}
+
+void dvmCompilerFindInductionVariables(struct CompilationUnit *cUnit,
+ struct BasicBlock *bb)
+{
+ BitVector *isIndVarV = cUnit->loopAnalysis->isIndVarV;
+ BitVector *isConstantV = cUnit->isConstantV;
+ GrowableList *ivList = cUnit->loopAnalysis->ivList;
+ MIR *mir;
+
+ if (bb->blockType != DALVIK_BYTECODE &&
+ bb->blockType != ENTRY_BLOCK) {
+ return;
+ }
+
+ /* If the bb doesn't have a phi it cannot contain an induction variable */
+ if (bb->firstMIRInsn == NULL ||
+ bb->firstMIRInsn->dalvikInsn.opCode != MIR_OP_PHI) {
+ return;
+ }
+
+ /* Find basic induction variable first */
+ for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
+ int dfAttributes =
+ dvmCompilerDataFlowAttributes[mir->dalvikInsn.opCode];
+
+ if (!(dfAttributes & DF_IS_LINEAR)) continue;
+
+ /*
+ * For a basic induction variable:
+ * 1) use[0] should belong to the output of a phi node
+ * 2) def[0] should belong to the input of the same phi node
+ * 3) the value added/subtracted is a constant
+ */
+ MIR *phi;
+ for (phi = bb->firstMIRInsn; phi; phi = phi->next) {
+ if (phi->dalvikInsn.opCode != MIR_OP_PHI) break;
+
+ if (phi->ssaRep->defs[0] == mir->ssaRep->uses[0] &&
+ phi->ssaRep->uses[1] == mir->ssaRep->defs[0]) {
+ bool deltaIsConstant = false;
+ int deltaValue;
+
+ switch (mir->dalvikInsn.opCode) {
+ case OP_ADD_INT:
+ if (dvmIsBitSet(isConstantV,
+ mir->ssaRep->uses[1])) {
+ deltaValue =
+ cUnit->constantValues[mir->ssaRep->uses[1]];
+ deltaIsConstant = true;
+ }
+ break;
+ case OP_SUB_INT:
+ if (dvmIsBitSet(isConstantV,
+ mir->ssaRep->uses[1])) {
+ deltaValue =
+ -cUnit->constantValues[mir->ssaRep->uses[1]];
+ deltaIsConstant = true;
+ }
+ break;
+ case OP_ADD_INT_LIT8:
+ deltaValue = mir->dalvikInsn.vC;
+ deltaIsConstant = true;
+ break;
+ default:
+ break;
+ }
+ if (deltaIsConstant) {
+ dvmSetBit(isIndVarV, mir->ssaRep->uses[0]);
+ InductionVariableInfo *ivInfo =
+ dvmCompilerNew(sizeof(InductionVariableInfo),
+ false);
+
+ ivInfo->ssaReg = mir->ssaRep->uses[0];
+ ivInfo->basicSSAReg = mir->ssaRep->uses[0];
+ ivInfo->m = 1; // always 1 to basic iv
+ ivInfo->c = 0; // N/A to basic iv
+ ivInfo->inc = deltaValue;
+ dvmInsertGrowableList(ivList, (void *) ivInfo);
+ cUnit->loopAnalysis->numBasicIV++;
+ break;
+ }
+ }
+ }
+ }
+
+ /* Find dependent induction variable now */
+ for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
+ int dfAttributes =
+ dvmCompilerDataFlowAttributes[mir->dalvikInsn.opCode];
+
+ if (!(dfAttributes & DF_IS_LINEAR)) continue;
+
+ /* Skip already identified induction variables */
+ if (dvmIsBitSet(isIndVarV, mir->ssaRep->defs[0])) continue;
+
+ /*
+ * For a dependent induction variable:
+ * 1) use[0] should be an induction variable (basic/dependent)
+ * 2) operand2 should be a constant
+ */
+ if (dvmIsBitSet(isIndVarV, mir->ssaRep->uses[0])) {
+ int srcDalvikReg = dvmConvertSSARegToDalvik(cUnit,
+ mir->ssaRep->uses[0]);
+ int dstDalvikReg = dvmConvertSSARegToDalvik(cUnit,
+ mir->ssaRep->defs[0]);
+
+ bool cIsConstant = false;
+ int c = 0;
+
+ switch (mir->dalvikInsn.opCode) {
+ case OP_ADD_INT:
+ if (dvmIsBitSet(isConstantV,
+ mir->ssaRep->uses[1])) {
+ c = cUnit->constantValues[mir->ssaRep->uses[1]];
+ cIsConstant = true;
+ }
+ break;
+ case OP_SUB_INT:
+ if (dvmIsBitSet(isConstantV,
+ mir->ssaRep->uses[1])) {
+ c = -cUnit->constantValues[mir->ssaRep->uses[1]];
+ cIsConstant = true;
+ }
+ break;
+ case OP_ADD_INT_LIT8:
+ c = mir->dalvikInsn.vC;
+ cIsConstant = true;
+ break;
+ default:
+ break;
+ }
+
+ /* Ignore the update to the basic induction variable itself */
+ if (DECODE_REG(srcDalvikReg) == DECODE_REG(dstDalvikReg)) {
+ cUnit->loopAnalysis->ssaBIV = mir->ssaRep->defs[0];
+ cIsConstant = false;
+ }
+
+ if (cIsConstant) {
+ unsigned int i;
+ dvmSetBit(isIndVarV, mir->ssaRep->defs[0]);
+ InductionVariableInfo *ivInfo =
+ dvmCompilerNew(sizeof(InductionVariableInfo),
+ false);
+ InductionVariableInfo *ivInfoOld = NULL ;
+
+ for (i = 0; i < ivList->numUsed; i++) {
+ ivInfoOld = ivList->elemList[i];
+ if (ivInfoOld->ssaReg == mir->ssaRep->uses[0]) break;
+ }
+
+ /* Guaranteed to find an element */
+ assert(i < ivList->numUsed);
+
+ ivInfo->ssaReg = mir->ssaRep->defs[0];
+ ivInfo->basicSSAReg = ivInfoOld->basicSSAReg;
+ ivInfo->m = ivInfoOld->m;
+ ivInfo->c = c + ivInfoOld->c;
+ ivInfo->inc = ivInfoOld->inc;
+ dvmInsertGrowableList(ivList, (void *) ivInfo);
+ }
+ }
+ }
+}
+
+/* Setup the basic data structures for SSA conversion */
+void dvmInitializeSSAConversion(CompilationUnit *cUnit)
+{
+ int i;
+ int numDalvikReg = cUnit->method->registersSize;
+
+ cUnit->ssaToDalvikMap = dvmCompilerNew(sizeof(GrowableList), false);
+ dvmInitGrowableList(cUnit->ssaToDalvikMap, numDalvikReg);
+
+ /*
+ * Initial number of SSA registers is equal to the number of Dalvik
+ * registers.
+ */
+ cUnit->numSSARegs = numDalvikReg;
+
+ /*
+ * Initialize the SSA2Dalvik map list. For the first numDalvikReg elements,
+ * the subscript is 0 so we use the ENCODE_REG_SUB macro to encode the value
+ * into "(0 << 16) | i"
+ */
+ for (i = 0; i < numDalvikReg; i++) {
+ dvmInsertGrowableList(cUnit->ssaToDalvikMap,
+ (void *) ENCODE_REG_SUB(i, 0));
+ }
+
+ /*
+ * Initialize the DalvikToSSAMap map. The low 16 bit is the SSA register id,
+ * while the high 16 bit is the current subscript. The original Dalvik
+ * register N is mapped to SSA register N with subscript 0.
+ */
+ cUnit->dalvikToSSAMap = dvmCompilerNew(sizeof(int) * numDalvikReg, false);
+ for (i = 0; i < numDalvikReg; i++) {
+ cUnit->dalvikToSSAMap[i] = i;
+ }
+
+ /*
+ * Allocate the BasicBlockDataFlow structure for the entry and code blocks
+ */
+ for (i = 0; i < cUnit->numBlocks; i++) {
+ BasicBlock *bb = cUnit->blockList[i];
+ if (bb->blockType == DALVIK_BYTECODE ||
+ bb->blockType == ENTRY_BLOCK) {
+ bb->dataFlowInfo = dvmCompilerNew(sizeof(BasicBlockDataFlow), true);
+ }
+ }
+}
+
+void dvmCompilerDataFlowAnalysisDispatcher(CompilationUnit *cUnit,
+ void (*func)(CompilationUnit *, BasicBlock *))
+{
+ int i;
+ for (i = 0; i < cUnit->numBlocks; i++) {
+ BasicBlock *bb = cUnit->blockList[i];
+ (*func)(cUnit, bb);
+ }
+}
+
+/* Main entry point to do SSA conversion for non-loop traces */
+void dvmCompilerNonLoopAnalysis(CompilationUnit *cUnit)
+{
+ dvmCompilerDataFlowAnalysisDispatcher(cUnit, dvmCompilerDoSSAConversion);
+}
diff --git a/vm/compiler/Dataflow.h b/vm/compiler/Dataflow.h
new file mode 100644
index 0000000..e4ae93d
--- /dev/null
+++ b/vm/compiler/Dataflow.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef _DALVIK_VM_DATAFLOW
+#define _DALVIK_VM_DATAFLOW
+
+#include "Dalvik.h"
+#include "CompilerInternals.h"
+
+typedef enum DataFlowAttributePos {
+ kUA = 0,
+ kUB,
+ kUC,
+ kUAWide,
+ kUBWide,
+ kUCWide,
+ kDA,
+ kDAWide,
+ kIsMove,
+ kIsLinear,
+ kSetsConst,
+ kFormat35c,
+ kFormat3rc,
+ kPhi,
+ kNullNRangeCheck0,
+ kNullNRangeCheck1,
+ kNullNRangeCheck2,
+} DataFlowAttributes;
+
+#define DF_NOP 0
+#define DF_UA (1 << kUA)
+#define DF_UB (1 << kUB)
+#define DF_UC (1 << kUC)
+#define DF_UA_WIDE (1 << kUAWide)
+#define DF_UB_WIDE (1 << kUBWide)
+#define DF_UC_WIDE (1 << kUCWide)
+#define DF_DA (1 << kDA)
+#define DF_DA_WIDE (1 << kDAWide)
+#define DF_IS_MOVE (1 << kIsMove)
+#define DF_IS_LINEAR (1 << kIsLinear)
+#define DF_SETS_CONST (1 << kSetsConst)
+#define DF_FORMAT_35C (1 << kFormat35c)
+#define DF_FORMAT_3RC (1 << kFormat3rc)
+#define DF_PHI (1 << kPhi)
+#define DF_NULL_N_RANGE_CHECK_0 (1 << kNullNRangeCheck0)
+#define DF_NULL_N_RANGE_CHECK_1 (1 << kNullNRangeCheck1)
+#define DF_NULL_N_RANGE_CHECK_2 (1 << kNullNRangeCheck2)
+
+#define DF_HAS_USES (DF_UA | DF_UB | DF_UC | DF_UA_WIDE | \
+ DF_UB_WIDE | DF_UC_WIDE)
+
+#define DF_HAS_DEFS (DF_DA | DF_DA_WIDE)
+
+#define DF_HAS_NR_CHECKS (DF_NULL_N_RANGE_CHECK_0 | \
+ DF_NULL_N_RANGE_CHECK_1 | \
+ DF_NULL_N_RANGE_CHECK_2)
+
+extern int dvmCompilerDataFlowAttributes[MIR_OP_LAST];
+
+typedef struct BasicBlockDataFlow {
+ BitVector *useV;
+ BitVector *defV;
+ BitVector *liveInV;
+ BitVector *phiV;
+ int *dalvikToSSAMap;
+} BasicBlockDataFlow;
+
+typedef struct SSARepresentation {
+ int numUses;
+ int *uses;
+ int numDefs;
+ int *defs;
+} SSARepresentation;
+
+typedef struct InductionVariableInfo {
+ int ssaReg;
+ int basicSSAReg;
+ int m;
+ int c;
+ int inc;
+} InductionVariableInfo;
+
+typedef struct ArrayAccessInfo {
+ int arrayReg;
+ int ivReg;
+ int maxC; // For DIV - will affect upper bound checking
+ int minC; // For DIV - will affect lower bound checking
+} ArrayAccessInfo;
+
+#define ENCODE_REG_SUB(r,s) ((s<<16) | r)
+#define DECODE_REG(v) (v & 0xffff)
+#define DECODE_SUB(v) (((unsigned int) v) >> 16)
+
+#endif /* _DALVIK_VM_DATAFLOW */
diff --git a/vm/compiler/Frontend.c b/vm/compiler/Frontend.c
index 66060a0..163cdf8 100644
--- a/vm/compiler/Frontend.c
+++ b/vm/compiler/Frontend.c
@@ -47,6 +47,8 @@
return insnWidth;
}
+#define UNKNOWN_TARGET 0xffffffff
+
/*
* Identify block-ending instructions and collect supplemental information
* regarding the following instructions.
@@ -63,6 +65,8 @@
case OP_RETURN_WIDE:
case OP_RETURN_OBJECT:
case OP_THROW:
+ *target = UNKNOWN_TARGET;
+ break;
case OP_INVOKE_VIRTUAL:
case OP_INVOKE_VIRTUAL_RANGE:
case OP_INVOKE_INTERFACE:
@@ -146,7 +150,8 @@
default:
return false;
- } return true;
+ }
+ return true;
}
/*
@@ -262,7 +267,7 @@
methodStats = analyzeMethodBody(desc->method);
cUnit.registerScoreboard.nullCheckedRegs =
- dvmAllocBitVector(desc->method->registersSize, false);
+ dvmCompilerAllocBitVector(desc->method->registersSize, false);
/* Initialize the printMe flag */
cUnit.printMe = gDvmJit.printMe;
@@ -333,11 +338,20 @@
}
}
- /* Allocate the first basic block */
- lastBB = startBB = curBB = dvmCompilerNewBB(DALVIK_BYTECODE);
+ /* Allocate the entry block */
+ lastBB = startBB = curBB = dvmCompilerNewBB(ENTRY_BLOCK);
curBB->startOffset = curOffset;
curBB->id = numBlocks++;
+ curBB = dvmCompilerNewBB(DALVIK_BYTECODE);
+ curBB->startOffset = curOffset;
+ curBB->id = numBlocks++;
+
+ /* Make the first real dalvik block the fallthrough of the entry block */
+ startBB->fallThrough = curBB;
+ lastBB->next = curBB;
+ lastBB = curBB;
+
if (cUnit.printMe) {
LOGD("--------\nCompiler: Building trace for %s, offset 0x%x\n",
desc->method->name, curOffset);
@@ -350,7 +364,7 @@
while (1) {
MIR *insn;
int width;
- insn = dvmCompilerNew(sizeof(MIR),false);
+ insn = dvmCompilerNew(sizeof(MIR), true);
insn->offset = curOffset;
width = parseInsn(codePtr, &insn->dalvikInsn, cUnit.printMe);
@@ -394,9 +408,9 @@
*/
for (curBB = startBB; curBB; curBB = curBB->next) {
MIR *lastInsn = curBB->lastMIRInsn;
- /* Hit a pseudo block - exit the search now */
+ /* Skip empty blocks */
if (lastInsn == NULL) {
- break;
+ continue;
}
curOffset = lastInsn->offset;
unsigned int targetOffset = curOffset;
@@ -436,33 +450,63 @@
kInstrInvoke)) == 0) ||
(lastInsn->dalvikInsn.opCode == OP_INVOKE_DIRECT_EMPTY);
-
- /* Target block not included in the trace */
if (curBB->taken == NULL &&
- (isInvoke || (targetOffset != curOffset))) {
- BasicBlock *newBB;
- if (isInvoke) {
- /* Monomorphic callee */
- if (callee) {
- newBB = dvmCompilerNewBB(CHAINING_CELL_INVOKE_SINGLETON);
- newBB->startOffset = 0;
- newBB->containingMethod = callee;
- /* Will resolve at runtime */
- } else {
- newBB = dvmCompilerNewBB(CHAINING_CELL_INVOKE_PREDICTED);
- newBB->startOffset = 0;
- }
- /* For unconditional branches, request a hot chaining cell */
- } else {
- newBB = dvmCompilerNewBB(flags & kInstrUnconditional ?
- CHAINING_CELL_HOT :
- CHAINING_CELL_NORMAL);
- newBB->startOffset = targetOffset;
+ curBB->fallThrough == NULL &&
+ flags == (kInstrCanBranch | kInstrCanContinue) &&
+ fallThroughOffset == startBB->startOffset) {
+ BasicBlock *loopBranch = curBB;
+ BasicBlock *exitBB;
+ BasicBlock *exitChainingCell;
+
+ if (cUnit.printMe) {
+ LOGD("Natural loop detected!");
}
- newBB->id = numBlocks++;
- curBB->taken = newBB;
- lastBB->next = newBB;
- lastBB = newBB;
+ exitBB = dvmCompilerNewBB(EXIT_BLOCK);
+ lastBB->next = exitBB;
+ lastBB = exitBB;
+
+ exitBB->startOffset = targetOffset;
+ exitBB->id = numBlocks++;
+ exitBB->needFallThroughBranch = true;
+
+ loopBranch->taken = exitBB;
+#if defined(WITH_SELF_VERIFICATION)
+ BasicBlock *backwardCell =
+ dvmCompilerNewBB(CHAINING_CELL_BACKWARD_BRANCH);
+ lastBB->next = backwardCell;
+ lastBB = backwardCell;
+
+ backwardCell->startOffset = startBB->startOffset;
+ backwardCell->id = numBlocks++;
+ loopBranch->fallThrough = backwardCell;
+#elif defined(WITH_JIT_TUNING)
+ if (gDvmJit.profile) {
+ BasicBlock *backwardCell =
+ dvmCompilerNewBB(CHAINING_CELL_BACKWARD_BRANCH);
+ lastBB->next = backwardCell;
+ lastBB = backwardCell;
+
+ backwardCell->startOffset = startBB->startOffset;
+ backwardCell->id = numBlocks++;
+ loopBranch->fallThrough = backwardCell;
+ } else {
+ loopBranch->fallThrough = startBB->next;
+ }
+#else
+ loopBranch->fallThrough = startBB->next;
+#endif
+
+ /* Create the chaining cell as the fallthrough of the exit block */
+ exitChainingCell = dvmCompilerNewBB(CHAINING_CELL_NORMAL);
+ lastBB->next = exitChainingCell;
+ lastBB = exitChainingCell;
+
+ exitChainingCell->startOffset = targetOffset;
+ exitChainingCell->id = numBlocks++;
+
+ exitBB->fallThrough = exitChainingCell;
+
+ cUnit.hasLoop = true;
}
/* Fallthrough block not included in the trace */
@@ -482,6 +526,48 @@
lastBB->startOffset = fallThroughOffset;
curBB->fallThrough = lastBB;
}
+
+ /* Target block not included in the trace */
+ if (curBB->taken == NULL &&
+ (isInvoke || (targetOffset != UNKNOWN_TARGET &&
+ targetOffset != curOffset))) {
+ BasicBlock *newBB;
+ if (isInvoke) {
+ /* Monomorphic callee */
+ if (callee) {
+ newBB = dvmCompilerNewBB(CHAINING_CELL_INVOKE_SINGLETON);
+ newBB->startOffset = 0;
+ newBB->containingMethod = callee;
+ /* Will resolve at runtime */
+ } else {
+ newBB = dvmCompilerNewBB(CHAINING_CELL_INVOKE_PREDICTED);
+ newBB->startOffset = 0;
+ }
+ /* For unconditional branches, request a hot chaining cell */
+ } else {
+#if !defined(WITH_SELF_VERIFICATION)
+ newBB = dvmCompilerNewBB(flags & kInstrUnconditional ?
+ CHAINING_CELL_HOT :
+ CHAINING_CELL_NORMAL);
+ newBB->startOffset = targetOffset;
+#else
+ /* Handle branches that branch back into the block */
+ if (targetOffset >= curBB->firstMIRInsn->offset &&
+ targetOffset <= curBB->lastMIRInsn->offset) {
+ newBB = dvmCompilerNewBB(CHAINING_CELL_BACKWARD_BRANCH);
+ } else {
+ newBB = dvmCompilerNewBB(flags & kInstrUnconditional ?
+ CHAINING_CELL_HOT :
+ CHAINING_CELL_NORMAL);
+ }
+ newBB->startOffset = targetOffset;
+#endif
+ }
+ newBB->id = numBlocks++;
+ curBB->taken = newBB;
+ lastBB->next = newBB;
+ lastBB = newBB;
+ }
}
/* Now create a special block to host PC reconstruction code */
@@ -524,6 +610,16 @@
/* Make sure all blocks are added to the cUnit */
assert(curBB == NULL);
+ /* Preparation for SSA conversion */
+ dvmInitializeSSAConversion(&cUnit);
+
+ if (cUnit.hasLoop) {
+ dvmCompilerLoopOpt(&cUnit);
+ }
+ else {
+ dvmCompilerNonLoopAnalysis(&cUnit);
+ }
+
if (cUnit.printMe) {
dvmCompilerDumpCompilationUnit(&cUnit);
}
@@ -551,11 +647,8 @@
/* Reset the compiler resource pool */
dvmCompilerArenaReset();
- /* Free the bit vector tracking null-checked registers */
- dvmFreeBitVector(cUnit.registerScoreboard.nullCheckedRegs);
-
- if (!cUnit.halveInstCount) {
/* Success */
+ if (!cUnit.halveInstCount) {
methodStats->nativeSize += cUnit.totalSize;
return info->codeAddress != NULL;
@@ -584,15 +677,16 @@
firstBlock->id = blockID++;
/* Allocate the bit-vector to track the beginning of basic blocks */
- BitVector *bbStartAddr = dvmAllocBitVector(dexCode->insnsSize+1, false);
- dvmSetBit(bbStartAddr, 0);
+ BitVector *bbStartAddr = dvmCompilerAllocBitVector(dexCode->insnsSize+1,
+ false);
+ dvmCompilerSetBit(bbStartAddr, 0);
/*
* Sequentially go through every instruction first and put them in a single
* basic block. Identify block boundaries at the mean time.
*/
while (codePtr < codeEnd) {
- MIR *insn = dvmCompilerNew(sizeof(MIR), false);
+ MIR *insn = dvmCompilerNew(sizeof(MIR), true);
insn->offset = curOffset;
int width = parseInsn(codePtr, &insn->dalvikInsn, false);
bool isInvoke = false;
@@ -616,9 +710,9 @@
*/
if (findBlockBoundary(method, insn, curOffset, &target, &isInvoke,
&callee)) {
- dvmSetBit(bbStartAddr, curOffset + width);
+ dvmCompilerSetBit(bbStartAddr, curOffset + width);
if (target != curOffset) {
- dvmSetBit(bbStartAddr, target);
+ dvmCompilerSetBit(bbStartAddr, target);
}
}
@@ -699,8 +793,6 @@
dvmAbort();
}
- dvmFreeBitVector(bbStartAddr);
-
/* Connect the basic blocks through the taken links */
for (i = 0; i < numBlocks; i++) {
BasicBlock *curBB = blockList[i];
diff --git a/vm/compiler/IntermediateRep.c b/vm/compiler/IntermediateRep.c
index 91b7af7..018d890 100644
--- a/vm/compiler/IntermediateRep.c
+++ b/vm/compiler/IntermediateRep.c
@@ -29,7 +29,7 @@
void dvmCompilerAppendMIR(BasicBlock *bb, MIR *mir)
{
if (bb->firstMIRInsn == NULL) {
- assert(bb->firstMIRInsn == NULL);
+ assert(bb->lastMIRInsn == NULL);
bb->lastMIRInsn = bb->firstMIRInsn = mir;
mir->prev = mir->next = NULL;
} else {
@@ -40,6 +40,21 @@
}
}
+/* Insert an MIR instruction to the head of a basic block */
+void dvmCompilerPrependMIR(BasicBlock *bb, MIR *mir)
+{
+ if (bb->firstMIRInsn == NULL) {
+ assert(bb->lastMIRInsn == NULL);
+ bb->lastMIRInsn = bb->firstMIRInsn = mir;
+ mir->prev = mir->next = NULL;
+ } else {
+ bb->firstMIRInsn->prev = mir;
+ mir->next = bb->firstMIRInsn;
+ mir->prev = NULL;
+ bb->firstMIRInsn = mir;
+ }
+}
+
/*
* Append an LIR instruction to the LIR list maintained by a compilation
* unit
@@ -75,3 +90,17 @@
newLIR->next = currentLIR;
currentLIR->prev = newLIR;
}
+
+/*
+ * Insert an LIR instruction after the current instruction, which cannot be the
+ * first instruction.
+ *
+ * currentLIR -> newLIR -> oldNext
+ */
+void dvmCompilerInsertLIRAfter(LIR *currentLIR, LIR *newLIR)
+{
+ newLIR->prev = currentLIR;
+ newLIR->next = currentLIR->next;
+ currentLIR->next = newLIR;
+ newLIR->next->prev = newLIR;
+}
diff --git a/vm/compiler/Loop.c b/vm/compiler/Loop.c
new file mode 100644
index 0000000..ffd5883
--- /dev/null
+++ b/vm/compiler/Loop.c
@@ -0,0 +1,512 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#include "Dalvik.h"
+#include "CompilerInternals.h"
+#include "Dataflow.h"
+#include "Loop.h"
+
+#define DEBUG_LOOP(X)
+
+/*
+ * Given the current simple natural loops, the phi node placement can be
+ * determined in the following fashion:
+ * entry (B0)
+ * +---v v
+ * | loop body (B1)
+ * | v
+ * | loop back (B2)
+ * +---+ v
+ * exit (B3)
+ *
+ * 1) Add live-ins of B1 to B0 as defs
+ * 2) The intersect of defs(B0)/defs(B1) and defs(B2)/def(B0) are the variables
+ * that need PHI nodes in B1.
+ */
+static void handlePhiPlacement(CompilationUnit *cUnit)
+{
+ BasicBlock *entry = cUnit->blockList[0];
+ BasicBlock *loopBody = cUnit->blockList[1];
+ BasicBlock *loopBranch = cUnit->blockList[2];
+ dvmCopyBitVector(entry->dataFlowInfo->defV,
+ loopBody->dataFlowInfo->liveInV);
+
+ BitVector *phiV = dvmCompilerAllocBitVector(cUnit->method->registersSize,
+ false);
+ dvmIntersectBitVectors(phiV, entry->dataFlowInfo->defV,
+ loopBody->dataFlowInfo->defV);
+ dvmIntersectBitVectors(phiV, entry->dataFlowInfo->defV,
+ loopBranch->dataFlowInfo->defV);
+
+ /* Insert the PHI MIRs */
+ int i;
+ for (i = 0; i < cUnit->method->registersSize; i++) {
+ if (!dvmIsBitSet(phiV, i)) {
+ continue;
+ }
+ MIR *phi = dvmCompilerNew(sizeof(MIR), true);
+ phi->dalvikInsn.opCode = MIR_OP_PHI;
+ phi->dalvikInsn.vA = i;
+ dvmCompilerPrependMIR(loopBody, phi);
+ }
+}
+
+static void fillPhiNodeContents(CompilationUnit *cUnit)
+{
+ BasicBlock *entry = cUnit->blockList[0];
+ BasicBlock *loopBody = cUnit->blockList[1];
+ BasicBlock *loopBranch = cUnit->blockList[2];
+ MIR *mir;
+
+ for (mir = loopBody->firstMIRInsn; mir; mir = mir->next) {
+ if (mir->dalvikInsn.opCode != MIR_OP_PHI) break;
+ int dalvikReg = mir->dalvikInsn.vA;
+
+ mir->ssaRep->numUses = 2;
+ mir->ssaRep->uses = dvmCompilerNew(sizeof(int) * 2, false);
+ mir->ssaRep->uses[0] =
+ DECODE_REG(entry->dataFlowInfo->dalvikToSSAMap[dalvikReg]);
+ mir->ssaRep->uses[1] =
+ DECODE_REG(loopBranch->dataFlowInfo->dalvikToSSAMap[dalvikReg]);
+ }
+
+
+}
+
+static void dumpConstants(CompilationUnit *cUnit)
+{
+ int i;
+ for (i = 0; i < cUnit->numSSARegs; i++) {
+ if (dvmIsBitSet(cUnit->isConstantV, i)) {
+ int subNReg = dvmConvertSSARegToDalvik(cUnit, i);
+ LOGE("s%d(v%d_%d) has %d", i,
+ DECODE_REG(subNReg), DECODE_SUB(subNReg),
+ cUnit->constantValues[i]);
+ }
+ }
+}
+
+static void dumpIVList(CompilationUnit *cUnit)
+{
+ unsigned int i;
+ GrowableList *ivList = cUnit->loopAnalysis->ivList;
+ int *ssaToDalvikMap = (int *) cUnit->ssaToDalvikMap->elemList;
+
+ for (i = 0; i < ivList->numUsed; i++) {
+ InductionVariableInfo *ivInfo = ivList->elemList[i];
+ /* Basic IV */
+ if (ivInfo->ssaReg == ivInfo->basicSSAReg) {
+ LOGE("BIV %d: s%d(v%d) + %d", i,
+ ivInfo->ssaReg,
+ ssaToDalvikMap[ivInfo->ssaReg] & 0xffff,
+ ivInfo->inc);
+ /* Dependent IV */
+ } else {
+ LOGE("DIV %d: s%d(v%d) = %d * s%d(v%d) + %d", i,
+ ivInfo->ssaReg,
+ ssaToDalvikMap[ivInfo->ssaReg] & 0xffff,
+ ivInfo->m,
+ ivInfo->basicSSAReg,
+ ssaToDalvikMap[ivInfo->basicSSAReg] & 0xffff,
+ ivInfo->c);
+ }
+ }
+}
+
+/*
+ * A loop is considered optimizable if:
+ * 1) It has one basic induction variable
+ * 2) The loop back branch compares the BIV with a constant
+ * 3) If it is a count-up loop, the condition is GE/GT, or LE/LT/LEZ/LTZ for
+ * a count-down loop.
+ */
+static bool isLoopOptimizable(CompilationUnit *cUnit)
+{
+ unsigned int i;
+ BasicBlock *loopBranch = cUnit->blockList[2];
+ LoopAnalysis *loopAnalysis = cUnit->loopAnalysis;
+
+ if (loopAnalysis->numBasicIV != 1) return false;
+ for (i = 0; i < loopAnalysis->ivList->numUsed; i++) {
+ InductionVariableInfo *ivInfo;
+
+ ivInfo = GET_ELEM_N(loopAnalysis->ivList, InductionVariableInfo*, i);
+ /* Count up or down loop? */
+ if (ivInfo->ssaReg == ivInfo->basicSSAReg) {
+ loopAnalysis->isCountUpLoop = ivInfo->inc > 0;
+ break;
+ }
+ }
+
+ MIR *branch = loopBranch->lastMIRInsn;
+ OpCode opCode = branch->dalvikInsn.opCode;
+
+ /*
+ * If the instruction is not accessing the IV as the first operand, return
+ * false.
+ */
+ if (branch->ssaRep->numUses == 0 || branch->ssaRep->numDefs != 0) {
+ return false;
+ }
+
+ /*
+ * If the first operand of the comparison is not the basic induction
+ * variable, return false.
+ */
+ if (branch->ssaRep->uses[0] != loopAnalysis->ssaBIV) {
+ return false;
+ }
+
+ if (loopAnalysis->isCountUpLoop) {
+ /*
+ * If the condition op is not > or >=, this is not an optimization
+ * candidate.
+ */
+ if (opCode != OP_IF_GT && opCode != OP_IF_GE) {
+ return false;
+ }
+ /*
+ * If the comparison is not between the BIV and a loop invariant,
+ * return false.
+ */
+ int endReg = dvmConvertSSARegToDalvik(cUnit, branch->ssaRep->uses[1]);
+
+ if (DECODE_SUB(endReg) != 0) {
+ return false;
+ }
+ loopAnalysis->endConditionReg = DECODE_REG(endReg);
+ } else {
+ /*
+ * If the condition op is not < or <=, this is not an optimization
+ * candidate.
+ */
+ if (opCode == OP_IF_LT || opCode == OP_IF_LE) {
+ /*
+ * If the comparison is not between the BIV and a loop invariant,
+ * return false.
+ */
+ int endReg = dvmConvertSSARegToDalvik(cUnit,
+ branch->ssaRep->uses[1]);
+
+ if (DECODE_SUB(endReg) != 0) {
+ return false;
+ }
+ loopAnalysis->endConditionReg = DECODE_REG(endReg);
+ } else if (opCode != OP_IF_LTZ && opCode != OP_IF_LEZ) {
+ return false;
+ }
+ }
+ loopAnalysis->loopBranchOpcode = opCode;
+ return true;
+}
+
+/*
+ * Record the upper and lower bound information for range checks for each
+ * induction variable. If array A is accessed by index "i+5", the upper and
+ * lower bound will be len(A)-5 and -5, respectively.
+ */
+static void updateRangeCheckInfo(CompilationUnit *cUnit, int arrayReg,
+ int idxReg)
+{
+ InductionVariableInfo *ivInfo;
+ LoopAnalysis *loopAnalysis = cUnit->loopAnalysis;
+ unsigned int i, j;
+
+ for (i = 0; i < loopAnalysis->ivList->numUsed; i++) {
+ ivInfo = GET_ELEM_N(loopAnalysis->ivList, InductionVariableInfo*, i);
+ if (ivInfo->ssaReg == idxReg) {
+ ArrayAccessInfo *arrayAccessInfo = NULL;
+ for (j = 0; j < loopAnalysis->arrayAccessInfo->numUsed; j++) {
+ ArrayAccessInfo *existingArrayAccessInfo =
+ GET_ELEM_N(loopAnalysis->arrayAccessInfo,
+ ArrayAccessInfo*,
+ j);
+ if (existingArrayAccessInfo->arrayReg == arrayReg) {
+ if (ivInfo->c > existingArrayAccessInfo->maxC) {
+ existingArrayAccessInfo->maxC = ivInfo->c;
+ }
+ if (ivInfo->c < existingArrayAccessInfo->minC) {
+ existingArrayAccessInfo->minC = ivInfo->c;
+ }
+ arrayAccessInfo = existingArrayAccessInfo;
+ break;
+ }
+ }
+ if (arrayAccessInfo == NULL) {
+ arrayAccessInfo =
+ dvmCompilerNew(sizeof(ArrayAccessInfo), false);
+ arrayAccessInfo->ivReg = ivInfo->basicSSAReg;
+ arrayAccessInfo->arrayReg = arrayReg;
+ arrayAccessInfo->maxC = (ivInfo->c > 0) ? ivInfo->c : 0;
+ arrayAccessInfo->minC = (ivInfo->c < 0) ? ivInfo->c : 0;
+ dvmInsertGrowableList(loopAnalysis->arrayAccessInfo,
+ arrayAccessInfo);
+ }
+ break;
+ }
+ }
+}
+
+/* Returns true if the loop body cannot throw any exceptions */
+static bool doLoopBodyCodeMotion(CompilationUnit *cUnit)
+{
+ BasicBlock *entry = cUnit->blockList[0];
+ BasicBlock *loopBody = cUnit->blockList[1];
+ MIR *mir;
+ bool loopBodyCanThrow = false;
+ int numDalvikRegs = cUnit->method->registersSize;
+
+ for (mir = loopBody->firstMIRInsn; mir; mir = mir->next) {
+ DecodedInstruction *dInsn = &mir->dalvikInsn;
+ int dfAttributes =
+ dvmCompilerDataFlowAttributes[mir->dalvikInsn.opCode];
+
+ /* Skip extended MIR instructions */
+ if (dInsn->opCode > 255) continue;
+
+ int instrFlags = dexGetInstrFlags(gDvm.instrFlags, dInsn->opCode);
+
+ /* Instruction is clean */
+ if ((instrFlags & kInstrCanThrow) == 0) continue;
+
+ /*
+ * Currently we can only optimize away null and range checks. Punt on
+ * instructions that can throw due to other exceptions.
+ */
+ if (!(dfAttributes & DF_HAS_NR_CHECKS)) {
+ loopBodyCanThrow = true;
+ continue;
+ }
+
+ /*
+ * This comparison is redundant now, but we will have more than one
+ * group of flags to check soon.
+ */
+ if (dfAttributes & DF_HAS_NR_CHECKS) {
+ /*
+ * Check if the null check is applied on a loop invariant register?
+ * If the register's SSA id is less than the number of Dalvik
+ * registers, then it is loop invariant.
+ */
+ int refIdx;
+ switch (dfAttributes & DF_HAS_NR_CHECKS) {
+ case DF_NULL_N_RANGE_CHECK_0:
+ refIdx = 0;
+ break;
+ case DF_NULL_N_RANGE_CHECK_1:
+ refIdx = 1;
+ break;
+ case DF_NULL_N_RANGE_CHECK_2:
+ refIdx = 2;
+ break;
+ default:
+ refIdx = 0;
+ dvmAbort();
+ }
+
+ int useIdx = refIdx + 1;
+ int subNRegArray =
+ dvmConvertSSARegToDalvik(cUnit, mir->ssaRep->uses[refIdx]);
+ int arrayReg = DECODE_REG(subNRegArray);
+ int arraySub = DECODE_SUB(subNRegArray);
+
+ /*
+ * If the register is never updated in the loop (ie subscript == 0),
+ * it is an optimization candidate.
+ */
+ if (arraySub != 0) {
+ loopBodyCanThrow = true;
+ continue;
+ }
+
+ /*
+ * Then check if the range check can be hoisted out of the loop if
+ * it is basic or dependent induction variable.
+ */
+ if (dvmIsBitSet(cUnit->loopAnalysis->isIndVarV,
+ mir->ssaRep->uses[useIdx])) {
+ mir->OptimizationFlags |=
+ MIR_IGNORE_RANGE_CHECK | MIR_IGNORE_NULL_CHECK;
+ updateRangeCheckInfo(cUnit, mir->ssaRep->uses[refIdx],
+ mir->ssaRep->uses[useIdx]);
+ }
+ }
+ }
+
+ return !loopBodyCanThrow;
+}
+
+static void dumpHoistedChecks(CompilationUnit *cUnit)
+{
+ ArrayAccessInfo *arrayAccessInfo;
+ LoopAnalysis *loopAnalysis = cUnit->loopAnalysis;
+ unsigned int i;
+
+ for (i = 0; i < loopAnalysis->arrayAccessInfo->numUsed; i++) {
+ ArrayAccessInfo *arrayAccessInfo =
+ GET_ELEM_N(loopAnalysis->arrayAccessInfo,
+ ArrayAccessInfo*, i);
+ int arrayReg = DECODE_REG(
+ dvmConvertSSARegToDalvik(cUnit, arrayAccessInfo->arrayReg));
+ int idxReg = DECODE_REG(
+ dvmConvertSSARegToDalvik(cUnit, arrayAccessInfo->ivReg));
+ LOGE("Array access %d", i);
+ LOGE(" arrayReg %d", arrayReg);
+ LOGE(" idxReg %d", idxReg);
+ LOGE(" endReg %d", loopAnalysis->endConditionReg);
+ LOGE(" maxC %d", arrayAccessInfo->maxC);
+ LOGE(" minC %d", arrayAccessInfo->minC);
+ LOGE(" opcode %d", loopAnalysis->loopBranchOpcode);
+ }
+}
+
+static void genHoistedChecks(CompilationUnit *cUnit)
+{
+ unsigned int i;
+ BasicBlock *entry = cUnit->blockList[0];
+ LoopAnalysis *loopAnalysis = cUnit->loopAnalysis;
+ ArrayAccessInfo *arrayAccessInfo;
+ int globalMaxC = 0;
+ int globalMinC = 0;
+ /* Should be loop invariant */
+ int idxReg = 0;
+
+ for (i = 0; i < loopAnalysis->arrayAccessInfo->numUsed; i++) {
+ ArrayAccessInfo *arrayAccessInfo =
+ GET_ELEM_N(loopAnalysis->arrayAccessInfo,
+ ArrayAccessInfo*, i);
+ int arrayReg = DECODE_REG(
+ dvmConvertSSARegToDalvik(cUnit, arrayAccessInfo->arrayReg));
+ idxReg = DECODE_REG(
+ dvmConvertSSARegToDalvik(cUnit, arrayAccessInfo->ivReg));
+
+ MIR *rangeCheckMIR = dvmCompilerNew(sizeof(MIR), true);
+ rangeCheckMIR->dalvikInsn.opCode = (loopAnalysis->isCountUpLoop) ?
+ MIR_OP_NULL_N_RANGE_UP_CHECK : MIR_OP_NULL_N_RANGE_DOWN_CHECK;
+ rangeCheckMIR->dalvikInsn.vA = arrayReg;
+ rangeCheckMIR->dalvikInsn.vB = idxReg;
+ rangeCheckMIR->dalvikInsn.vC = loopAnalysis->endConditionReg;
+ rangeCheckMIR->dalvikInsn.arg[0] = arrayAccessInfo->maxC;
+ rangeCheckMIR->dalvikInsn.arg[1] = arrayAccessInfo->minC;
+ rangeCheckMIR->dalvikInsn.arg[2] = loopAnalysis->loopBranchOpcode;
+ dvmCompilerAppendMIR(entry, rangeCheckMIR);
+ if (arrayAccessInfo->maxC > globalMaxC) {
+ globalMaxC = arrayAccessInfo->maxC;
+ }
+ if (arrayAccessInfo->minC < globalMinC) {
+ globalMinC = arrayAccessInfo->minC;
+ }
+ }
+
+ if (loopAnalysis->arrayAccessInfo->numUsed != 0) {
+ if (loopAnalysis->isCountUpLoop) {
+ MIR *boundCheckMIR = dvmCompilerNew(sizeof(MIR), true);
+ boundCheckMIR->dalvikInsn.opCode = MIR_OP_LOWER_BOUND_CHECK;
+ boundCheckMIR->dalvikInsn.vA = idxReg;
+ boundCheckMIR->dalvikInsn.vB = globalMinC;
+ dvmCompilerAppendMIR(entry, boundCheckMIR);
+ } else {
+ if (loopAnalysis->loopBranchOpcode == OP_IF_LT ||
+ loopAnalysis->loopBranchOpcode == OP_IF_LE) {
+ MIR *boundCheckMIR = dvmCompilerNew(sizeof(MIR), true);
+ boundCheckMIR->dalvikInsn.opCode = MIR_OP_LOWER_BOUND_CHECK;
+ boundCheckMIR->dalvikInsn.vA = loopAnalysis->endConditionReg;
+ boundCheckMIR->dalvikInsn.vB = globalMinC;
+ /*
+ * If the end condition is ">", add 1 back to the constant field
+ * to reflect the fact that the smallest index value is
+ * "endValue + constant + 1".
+ */
+ if (loopAnalysis->loopBranchOpcode == OP_IF_LT) {
+ boundCheckMIR->dalvikInsn.vB++;
+ }
+ dvmCompilerAppendMIR(entry, boundCheckMIR);
+ } else if (loopAnalysis->loopBranchOpcode == OP_IF_LTZ) {
+ /* Array index will fall below 0 */
+ if (globalMinC < 0) {
+ MIR *boundCheckMIR = dvmCompilerNew(sizeof(MIR), true);
+ boundCheckMIR->dalvikInsn.opCode = MIR_OP_PUNT;
+ dvmCompilerAppendMIR(entry, boundCheckMIR);
+ }
+ } else if (loopAnalysis->loopBranchOpcode == OP_IF_LEZ) {
+ /* Array index will fall below 0 */
+ if (globalMinC < -1) {
+ MIR *boundCheckMIR = dvmCompilerNew(sizeof(MIR), true);
+ boundCheckMIR->dalvikInsn.opCode = MIR_OP_PUNT;
+ dvmCompilerAppendMIR(entry, boundCheckMIR);
+ }
+ } else {
+ dvmAbort();
+ }
+ }
+
+ }
+}
+
+/* Main entry point to do loop optimization */
+void dvmCompilerLoopOpt(CompilationUnit *cUnit)
+{
+ int numDalvikReg = cUnit->method->registersSize;
+ LoopAnalysis *loopAnalysis = dvmCompilerNew(sizeof(LoopAnalysis), true);
+
+ assert(cUnit->blockList[0]->blockType == ENTRY_BLOCK);
+ assert(cUnit->blockList[2]->blockType == DALVIK_BYTECODE);
+ assert(cUnit->blockList[3]->blockType == EXIT_BLOCK);
+
+ cUnit->loopAnalysis = loopAnalysis;
+ /*
+ * Find live-in variables to the loop body so that we can fake their
+ * definitions in the entry block.
+ */
+ dvmCompilerDataFlowAnalysisDispatcher(cUnit, dvmCompilerFindLiveIn);
+
+ /* Insert phi nodes to the loop body */
+ handlePhiPlacement(cUnit);
+
+ dvmCompilerDataFlowAnalysisDispatcher(cUnit, dvmCompilerDoSSAConversion);
+ fillPhiNodeContents(cUnit);
+
+ /* Constant propagation */
+ cUnit->isConstantV = dvmAllocBitVector(cUnit->numSSARegs, false);
+ cUnit->constantValues = dvmCompilerNew(sizeof(int) * cUnit->numSSARegs,
+ true);
+ dvmCompilerDataFlowAnalysisDispatcher(cUnit,
+ dvmCompilerDoConstantPropagation);
+ DEBUG_LOOP(dumpConstants(cUnit);)
+
+ /* Find induction variables - basic and dependent */
+ loopAnalysis->ivList = dvmCompilerNew(sizeof(GrowableList), true);
+ dvmInitGrowableList(loopAnalysis->ivList, 4);
+ loopAnalysis->isIndVarV = dvmAllocBitVector(cUnit->numSSARegs, false);
+ dvmCompilerDataFlowAnalysisDispatcher(cUnit,
+ dvmCompilerFindInductionVariables);
+ DEBUG_LOOP(dumpIVList(cUnit);)
+
+ /* If the loop turns out to be non-optimizable, return early */
+ if (!isLoopOptimizable(cUnit))
+ return;
+
+ loopAnalysis->arrayAccessInfo = dvmCompilerNew(sizeof(GrowableList), true);
+ dvmInitGrowableList(loopAnalysis->arrayAccessInfo, 4);
+ loopAnalysis->bodyIsClean = doLoopBodyCodeMotion(cUnit);
+ DEBUG_LOOP(dumpHoistedChecks(cUnit);)
+
+ /*
+ * Convert the array access information into extended MIR code in the loop
+ * header.
+ */
+ genHoistedChecks(cUnit);
+}
diff --git a/vm/compiler/Loop.h b/vm/compiler/Loop.h
new file mode 100644
index 0000000..0de2baf
--- /dev/null
+++ b/vm/compiler/Loop.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef _DALVIK_VM_LOOP
+#define _DALVIK_VM_LOOP
+
+#include "Dalvik.h"
+#include "CompilerInternals.h"
+
+typedef struct LoopAnalysis {
+ BitVector *isIndVarV; // length == numSSAReg
+ GrowableList *ivList; // induction variables
+ GrowableList *arrayAccessInfo; // hoisted checks for array accesses
+ int numBasicIV; // number of basic induction variables
+ int ssaBIV; // basic IV in SSA name
+ bool isCountUpLoop; // count up or down loop
+ OpCode loopBranchOpcode; // OP_IF_XXX for the loop back branch
+ int endConditionReg; // vB in "vA op vB"
+ LIR *branchToBody; // branch over to the body from entry
+ LIR *branchToPCR; // branch over to the PCR cell
+ bool bodyIsClean; // loop body cannot throw any exceptions
+} LoopAnalysis;
+
+#endif /* _DALVIK_VM_LOOP */
diff --git a/vm/compiler/Utility.c b/vm/compiler/Utility.c
index 715f750..cbfea16 100644
--- a/vm/compiler/Utility.c
+++ b/vm/compiler/Utility.c
@@ -203,10 +203,80 @@
gDvmJit.compilerMaxQueued);
dvmJitStats();
dvmCompilerArchDump();
- dvmHashForeach(gDvmJit.methodStatsTable, dumpMethodStats,
- &totalMethodStats);
+ if (gDvmJit.methodStatsTable) {
+ dvmHashForeach(gDvmJit.methodStatsTable, dumpMethodStats,
+ &totalMethodStats);
+ }
LOGD("Code size stats: %d/%d (compiled/total Dalvik), %d (native)",
totalMethodStats.compiledDalvikSize,
totalMethodStats.dalvikSize,
totalMethodStats.nativeSize);
}
+
+/*
+ * Allocate a bit vector with enough space to hold at least the specified
+ * number of bits.
+ *
+ * NOTE: this is the sister implementation of dvmAllocBitVector. In this version
+ * memory is allocated from the compiler arena.
+ */
+BitVector* dvmCompilerAllocBitVector(int startBits, bool expandable)
+{
+ BitVector* bv;
+ int count;
+
+ assert(sizeof(bv->storage[0]) == 4); /* assuming 32-bit units */
+ assert(startBits >= 0);
+
+ bv = (BitVector*) dvmCompilerNew(sizeof(BitVector), false);
+
+ count = (startBits + 31) >> 5;
+
+ bv->storageSize = count;
+ bv->expandable = expandable;
+ bv->storage = (u4*) dvmCompilerNew(count * sizeof(u4), true);
+ return bv;
+}
+
+/*
+ * Mark the specified bit as "set".
+ *
+ * Returns "false" if the bit is outside the range of the vector and we're
+ * not allowed to expand.
+ *
+ * NOTE: this is the sister implementation of dvmSetBit. In this version
+ * memory is allocated from the compiler arena.
+ */
+bool dvmCompilerSetBit(BitVector *pBits, int num)
+{
+ assert(num >= 0);
+ if (num >= pBits->storageSize * (int)sizeof(u4) * 8) {
+ if (!pBits->expandable)
+ return false;
+
+ int newSize = (num + 31) >> 5;
+ assert(newSize > pBits->storageSize);
+ u4 *newStorage = dvmCompilerNew(newSize * sizeof(u4), false);
+ memcpy(newStorage, pBits->storage, pBits->storageSize * sizeof(u4));
+ memset(&newStorage[pBits->storageSize], 0,
+ (newSize - pBits->storageSize) * sizeof(u4));
+ pBits->storage = newStorage;
+ pBits->storageSize = newSize;
+ }
+
+ pBits->storage[num >> 5] |= 1 << (num & 0x1f);
+ return true;
+}
+
+/* FIXME */
+void dvmDebugBitVector(char *msg, const BitVector *bv, int length)
+{
+ int i;
+
+ LOGE("%s", msg);
+ for (i = 0; i < length; i++) {
+ if (dvmIsBitSet(bv, i)) {
+ LOGE("Bit %d is set", i);
+ }
+ }
+}
diff --git a/vm/compiler/codegen/CompilerCodegen.h b/vm/compiler/codegen/CompilerCodegen.h
index c9e6bd6..28e13a5 100644
--- a/vm/compiler/codegen/CompilerCodegen.h
+++ b/vm/compiler/codegen/CompilerCodegen.h
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-#include "../CompilerIR.h"
-
#ifndef _DALVIK_VM_COMPILERCODEGEN_H_
#define _DALVIK_VM_COMPILERCODEGEN_H_
+#include "compiler/CompilerIR.h"
+
/* Work unit is architecture dependent */
bool dvmCompilerDoWork(CompilerWorkOrder *work);
diff --git a/vm/compiler/codegen/Optimizer.h b/vm/compiler/codegen/Optimizer.h
index 1a891b1..487e864 100644
--- a/vm/compiler/codegen/Optimizer.h
+++ b/vm/compiler/codegen/Optimizer.h
@@ -14,12 +14,20 @@
* limitations under the License.
*/
-#include "Dalvik.h"
-#include "compiler/CompilerInternals.h"
-
#ifndef _DALVIK_VM_COMPILER_OPTIMIZATION_H
#define _DALVIK_VM_COMPILER_OPTIMIZATION_H
+#include "Dalvik.h"
+
+/*
+ * If the corresponding bit is set in gDvmJit.disableOpt, the selected
+ * optimization will be suppressed.
+ */
+typedef enum optControlVector {
+ kLoadStoreElimination = 0,
+ kLoadHoisting,
+} optControlVector;
+
/* Forward declarations */
struct CompilationUnit;
struct LIR;
@@ -36,6 +44,8 @@
int nativeReg; // And the mapped native register
int nativeRegHi; // And the mapped native register
bool isWide; // Whether a pair of registers are alive
+ int fp[32]; // Track the Dalvik register held in a SFP reg
+ int nextFP; // Next index for FP register allocation
} RegisterScoreboard;
void dvmCompilerApplyLocalOptimizations(struct CompilationUnit *cUnit,
diff --git a/vm/compiler/codegen/arm/ArchUtility.c b/vm/compiler/codegen/arm/ArchUtility.c
index 60c5cdb..d1f9870 100644
--- a/vm/compiler/codegen/arm/ArchUtility.c
+++ b/vm/compiler/codegen/arm/ArchUtility.c
@@ -79,9 +79,20 @@
strcpy(tbuf, "!");
} else {
assert(fmt < fmtEnd);
- assert((unsigned)(nc-'0') < 3);
+ assert((unsigned)(nc-'0') < 4);
operand = lir->operands[nc-'0'];
switch(*fmt++) {
+ case 'b':
+ strcpy(tbuf,"0000");
+ for (i=3; i>= 0; i--) {
+ tbuf[i] += operand & 1;
+ operand >>= 1;
+ }
+ break;
+ case 'n':
+ operand = ~expandImmediate(operand);
+ sprintf(tbuf,"%d [0x%x]", operand, operand);
+ break;
case 'm':
operand = expandImmediate(operand);
sprintf(tbuf,"%d [0x%x]", operand, operand);
@@ -99,9 +110,6 @@
case 'd':
sprintf(tbuf,"%d", operand);
break;
- case 'D':
- sprintf(tbuf,"%d", operand+8);
- break;
case 'E':
sprintf(tbuf,"%d", operand*4);
break;
@@ -111,28 +119,28 @@
case 'c':
switch (operand) {
case ARM_COND_EQ:
- strcpy(tbuf, "beq");
+ strcpy(tbuf, "eq");
break;
case ARM_COND_NE:
- strcpy(tbuf, "bne");
+ strcpy(tbuf, "ne");
break;
case ARM_COND_LT:
- strcpy(tbuf, "blt");
+ strcpy(tbuf, "lt");
break;
case ARM_COND_GE:
- strcpy(tbuf, "bge");
+ strcpy(tbuf, "ge");
break;
case ARM_COND_GT:
- strcpy(tbuf, "bgt");
+ strcpy(tbuf, "gt");
break;
case ARM_COND_LE:
- strcpy(tbuf, "ble");
+ strcpy(tbuf, "le");
break;
case ARM_COND_CS:
- strcpy(tbuf, "bcs");
+ strcpy(tbuf, "cs");
break;
case ARM_COND_MI:
- strcpy(tbuf, "bmi");
+ strcpy(tbuf, "mi");
break;
default:
strcpy(tbuf, "");
@@ -182,8 +190,49 @@
*buf = 0;
}
+void dvmDumpResourceMask(LIR *lir, u8 mask, const char *prefix)
+{
+ char buf[256];
+ buf[0] = 0;
+ ArmLIR *armLIR = (ArmLIR *) lir;
+
+ if (mask == ENCODE_ALL) {
+ strcpy(buf, "all");
+ } else {
+ char num[8];
+ int i;
+
+ for (i = 0; i < kRegEnd; i++) {
+ if (mask & (1ULL << i)) {
+ sprintf(num, "%d ", i);
+ strcat(buf, num);
+ }
+ }
+
+ if (mask & ENCODE_CCODE) {
+ strcat(buf, "cc ");
+ }
+ if (mask & ENCODE_FP_STATUS) {
+ strcat(buf, "fpcc ");
+ }
+ if (armLIR && (mask & ENCODE_DALVIK_REG)) {
+ sprintf(buf + strlen(buf), "dr%d%s", armLIR->aliasInfo & 0xffff,
+ (armLIR->aliasInfo & 0x80000000) ? "(+1)" : "");
+ }
+ }
+ if (buf[0]) {
+ LOGD("%s: %s", prefix, buf);
+ }
+}
+
+/*
+ * Debugging macros
+ */
+#define DUMP_RESOURCE_MASK(X)
+#define DUMP_SSA_REP(X)
+
/* Pretty-print a LIR instruction */
-static void dumpLIRInsn(LIR *arg, unsigned char *baseAddr)
+void dvmDumpLIRInsn(LIR *arg, unsigned char *baseAddr)
{
ArmLIR *lir = (ArmLIR *) arg;
char buf[256];
@@ -191,10 +240,23 @@
int offset = lir->generic.offset;
int dest = lir->operands[0];
u2 *cPtr = (u2*)baseAddr;
+ const bool dumpNop = false;
+
/* Handle pseudo-ops individually, and all regular insns as a group */
switch(lir->opCode) {
+ case ARM_PSEUDO_BARRIER:
+ LOGD("-------- BARRIER");
+ break;
+ case ARM_PSEUDO_EXTENDED_MIR:
+ /* intentional fallthrough */
+ case ARM_PSEUDO_SSA_REP:
+ DUMP_SSA_REP(LOGD("-------- %s\n", (char *) dest));
+ break;
case ARM_PSEUDO_TARGET_LABEL:
break;
+ case ARM_PSEUDO_CHAINING_CELL_BACKWARD_BRANCH:
+ LOGD("-------- chaining cell (backward branch): 0x%04x\n", dest);
+ break;
case ARM_PSEUDO_CHAINING_CELL_NORMAL:
LOGD("-------- chaining cell (normal): 0x%04x\n", dest);
break;
@@ -209,10 +271,16 @@
((Method *)dest)->name,
((Method *)dest)->insns);
break;
+ case ARM_PSEUDO_ENTRY_BLOCK:
+ LOGD("-------- entry offset: 0x%04x\n", dest);
+ break;
case ARM_PSEUDO_DALVIK_BYTECODE_BOUNDARY:
LOGD("-------- dalvik offset: 0x%04x @ %s\n", dest,
getOpcodeName(lir->operands[1]));
break;
+ case ARM_PSEUDO_EXIT_BLOCK:
+ LOGD("-------- exit offset: 0x%04x\n", dest);
+ break;
case ARM_PSEUDO_ALIGN4:
LOGD("%p (%04x): .align4\n", baseAddr + offset, offset);
break;
@@ -230,17 +298,27 @@
LOGD("L%#06x:\n", dest);
break;
default:
- if (lir->isNop) {
+ if (lir->isNop && !dumpNop) {
break;
}
buildInsnString(EncodingMap[lir->opCode].name, lir, opName,
baseAddr, 256);
buildInsnString(EncodingMap[lir->opCode].fmt, lir, buf, baseAddr,
256);
- LOGD("%p (%04x): %-8s%s\n",
- baseAddr + offset, offset, opName, buf);
+ LOGD("%p (%04x): %-8s%s%s\n",
+ baseAddr + offset, offset, opName, buf,
+ lir->isNop ? "(nop)" : "");
break;
}
+
+ if (lir->useMask && (!lir->isNop || dumpNop)) {
+ DUMP_RESOURCE_MASK(dvmDumpResourceMask((LIR *) lir,
+ lir->useMask, "use"));
+ }
+ if (lir->defMask && (!lir->isNop || dumpNop)) {
+ DUMP_RESOURCE_MASK(dvmDumpResourceMask((LIR *) lir,
+ lir->defMask, "def"));
+ }
}
/* Dump instructions and constant pool contents */
@@ -253,12 +331,13 @@
LOGD("installed code is at %p\n", cUnit->baseAddr);
LOGD("total size is %d bytes\n", cUnit->totalSize);
for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
- dumpLIRInsn(lirInsn, cUnit->baseAddr);
+ dvmDumpLIRInsn(lirInsn, cUnit->baseAddr);
}
for (lirInsn = cUnit->wordList; lirInsn; lirInsn = lirInsn->next) {
armLIR = (ArmLIR *) lirInsn;
LOGD("%p (%04x): .word (0x%x)\n",
- (char*)cUnit->baseAddr + armLIR->generic.offset, armLIR->generic.offset,
+ (char*)cUnit->baseAddr + armLIR->generic.offset,
+ armLIR->generic.offset,
armLIR->operands[0]);
}
}
diff --git a/vm/compiler/codegen/arm/ArmLIR.h b/vm/compiler/codegen/arm/ArmLIR.h
index 59c7529..8fedda2 100644
--- a/vm/compiler/codegen/arm/ArmLIR.h
+++ b/vm/compiler/codegen/arm/ArmLIR.h
@@ -27,7 +27,7 @@
* r6 (rGLUE) is reserved [holds current &interpState]
* r7 (rINST) is scratch for Jit
* r8 (rIBASE) is scratch for Jit, but must be restored when resuming interp
- * r9 is always scratch
+ * r9 is reserved
* r10 is always scratch
* r11 (fp) used by gcc unless -fomit-frame-pointer set [available for jit?]
* r12 is always scratch
@@ -35,21 +35,30 @@
* r14 (lr) is scratch for Jit
* r15 (pc) is reserved
*
+ * Preserved across C calls: r4, r5, r6, r7, r8, r10, r11
+ * Trashed across C calls: r0, r1, r2, r3, r12, r14
+ *
+ * Floating pointer registers
+ * s0-s31
+ * d0-d15, where d0={s0,s1}, d1={s2,s3}, ... , d15={s30,s31}
+ *
+ * s16-s31 (d8-d15) preserved across C calls
+ * s0-s15 (d0-d7) trashed across C calls
+ *
* For Thumb code use:
- * r0, r1, r2, r3 to hold operands/results via scoreboard
+ * r0, r1, r2, r3 to hold operands/results
* r4, r7 for temps
*
* For Thumb2 code use:
- * r0, r1, r2, r3, r8, r9, r10, r11 for operands/results via scoreboard
- * r4, r7, r14 for temps
+ * r0, r1, r2, r3, r8, r9, r10, r11, r12, r14 for operands/results
+ * r4, r7 for temps
+ * s16-s31/d8-d15 for operands/results
+ * s0-s15/d0-d7 for temps
*
* When transitioning from code cache to interp:
* restore rIBASE
* restore rPC
- * restore r11 (fp)?
- *
- * Double precision values are stored in consecutive single precision registers
- * such that dr0 -> (sr0,sr1), dr1 -> (sr2,sr3) ... dr16 -> (sr30,sr31)
+ * restore r11?
*/
/* Offset to distingish FP regs */
@@ -57,15 +66,87 @@
/* Offset to distinguish DP FP regs */
#define FP_DOUBLE 64
/* Reg types */
+#define REGTYPE(x) (x & (FP_REG_OFFSET | FP_DOUBLE))
#define FPREG(x) ((x & FP_REG_OFFSET) == FP_REG_OFFSET)
#define LOWREG(x) ((x & 0x7) == x)
#define DOUBLEREG(x) ((x & FP_DOUBLE) == FP_DOUBLE)
#define SINGLEREG(x) (FPREG(x) && !DOUBLEREG(x))
/* Mask to strip off fp flags */
#define FP_REG_MASK (FP_REG_OFFSET-1)
-/* Mask to convert high reg to low for Thumb */
-#define THUMB_REG_MASK 0x7
+/* non-existent Dalvik register */
+#define vNone (-1)
+/* non-existant physical register */
+#define rNone (-1)
+typedef enum ResourceEncodingPos {
+ kGPReg0 = 0,
+ kRegSP = 13,
+ kRegLR = 14,
+ kRegPC = 15,
+ kFPReg0 = 16,
+ kRegEnd = 48,
+ kCCode = kRegEnd,
+ kFPStatus,
+ kDalvikReg,
+} ResourceEncodingPos;
+
+#define ENCODE_REG_LIST(N) ((u8) N)
+#define ENCODE_REG_SP (1ULL << kRegSP)
+#define ENCODE_REG_LR (1ULL << kRegLR)
+#define ENCODE_REG_PC (1ULL << kRegPC)
+#define ENCODE_CCODE (1ULL << kCCode)
+#define ENCODE_FP_STATUS (1ULL << kFPStatus)
+#define ENCODE_DALVIK_REG (1ULL << kDalvikReg)
+#define ENCODE_ALL (~0ULL)
+
+#define DECODE_ALIAS_INFO_REG(X) (X & 0xffff)
+#define DECODE_ALIAS_INFO_WIDE(X) ((X & 0x80000000) ? 1 : 0)
+
+typedef enum OpSize {
+ WORD,
+ LONG,
+ SINGLE,
+ DOUBLE,
+ UNSIGNED_HALF,
+ SIGNED_HALF,
+ UNSIGNED_BYTE,
+ SIGNED_BYTE,
+} OpSize;
+
+typedef enum OpKind {
+ OP_MOV,
+ OP_MVN,
+ OP_CMP,
+ OP_LSL,
+ OP_LSR,
+ OP_ASR,
+ OP_ROR,
+ OP_NOT,
+ OP_AND,
+ OP_OR,
+ OP_XOR,
+ OP_NEG,
+ OP_ADD,
+ OP_ADC,
+ OP_SUB,
+ OP_SBC,
+ OP_RSUB,
+ OP_MUL,
+ OP_DIV,
+ OP_REM,
+ OP_BIC,
+ OP_CMN,
+ OP_TST,
+ OP_BKPT,
+ OP_BLX,
+ OP_PUSH,
+ OP_POP,
+ OP_2CHAR,
+ OP_2SHORT,
+ OP_2BYTE,
+ OP_COND_BR,
+ OP_UNCOND_BR,
+} OpKind;
typedef enum NativeRegisterPool {
r0 = 0,
@@ -138,12 +219,20 @@
typedef enum ArmConditionCode {
ARM_COND_EQ = 0x0, /* 0000 */
ARM_COND_NE = 0x1, /* 0001 */
- ARM_COND_LT = 0xb, /* 1011 */
+ ARM_COND_CS = 0x2, /* 0010 */
+ ARM_COND_CC = 0x3, /* 0011 */
+ ARM_COND_MI = 0x4, /* 0100 */
+ ARM_COND_PL = 0x5, /* 0101 */
+ ARM_COND_VS = 0x6, /* 0110 */
+ ARM_COND_VC = 0x7, /* 0111 */
+ ARM_COND_HI = 0x8, /* 1000 */
+ ARM_COND_LS = 0x9, /* 1001 */
ARM_COND_GE = 0xa, /* 1010 */
+ ARM_COND_LT = 0xb, /* 1011 */
ARM_COND_GT = 0xc, /* 1100 */
ARM_COND_LE = 0xd, /* 1101 */
- ARM_COND_CS = 0x2, /* 0010 */
- ARM_COND_MI = 0x4, /* 0100 */
+ ARM_COND_AL = 0xe, /* 1110 */
+ ARM_COND_NV = 0xf, /* 1111 */
} ArmConditionCode;
#define isPseudoOpCode(opCode) ((int)(opCode) < 0)
@@ -154,7 +243,13 @@
* Assemble.c.
*/
typedef enum ArmOpCode {
- ARM_PSEUDO_TARGET_LABEL = -11,
+ ARM_PSEUDO_BARRIER = -17,
+ ARM_PSEUDO_EXTENDED_MIR = -16,
+ ARM_PSEUDO_SSA_REP = -15,
+ ARM_PSEUDO_ENTRY_BLOCK = -14,
+ ARM_PSEUDO_EXIT_BLOCK = -13,
+ ARM_PSEUDO_TARGET_LABEL = -12,
+ ARM_PSEUDO_CHAINING_CELL_BACKWARD_BRANCH = -11,
ARM_PSEUDO_CHAINING_CELL_HOT = -10,
ARM_PSEUDO_CHAINING_CELL_INVOKE_PREDICTED = -9,
ARM_PSEUDO_CHAINING_CELL_INVOKE_SINGLETON = -8,
@@ -167,7 +262,7 @@
ARM_PSEUDO_NORMAL_BLOCK_LABEL = -1,
/************************************************************************/
ARM_16BIT_DATA, /* DATA [0] rd[15..0] */
- THUMB_ADC, /* adc [0100000101] rm[5..3] rd[2..0] */
+ THUMB_ADC_RR, /* adc [0100000101] rm[5..3] rd[2..0] */
THUMB_ADD_RRI3, /* add(1) [0001110] imm_3[8..6] rn[5..3] rd[2..0]*/
THUMB_ADD_RI8, /* add(2) [00110] rd[10..8] imm_8[7..0] */
THUMB_ADD_RRR, /* add(3) [0001100] rm[8..6] rn[5..3] rd[2..0] */
@@ -178,25 +273,25 @@
THUMB_ADD_SP_REL, /* add(6) [10101] rd[10..8] imm_8[7..0] */
THUMB_ADD_SPI7, /* add(7) [101100000] imm_7[6..0] */
THUMB_AND_RR, /* and [0100000000] rm[5..3] rd[2..0] */
- THUMB_ASR, /* asr(1) [00010] imm_5[10..6] rm[5..3] rd[2..0] */
- THUMB_ASRV, /* asr(2) [0100000100] rs[5..3] rd[2..0] */
+ THUMB_ASR_RRI5, /* asr(1) [00010] imm_5[10..6] rm[5..3] rd[2..0] */
+ THUMB_ASR_RR, /* asr(2) [0100000100] rs[5..3] rd[2..0] */
THUMB_B_COND, /* b(1) [1101] cond[11..8] offset_8[7..0] */
THUMB_B_UNCOND, /* b(2) [11100] offset_11[10..0] */
- THUMB_BIC, /* bic [0100001110] rm[5..3] rd[2..0] */
+ THUMB_BIC_RR, /* bic [0100001110] rm[5..3] rd[2..0] */
THUMB_BKPT, /* bkpt [10111110] imm_8[7..0] */
THUMB_BLX_1, /* blx(1) [111] H[10] offset_11[10..0] */
THUMB_BLX_2, /* blx(1) [111] H[01] offset_11[10..0] */
THUMB_BL_1, /* blx(1) [111] H[10] offset_11[10..0] */
THUMB_BL_2, /* blx(1) [111] H[11] offset_11[10..0] */
- THUMB_BLX_R, /* blx(2) [010001111] H2[6..6] rm[5..3] SBZ[000] */
+ THUMB_BLX_R, /* blx(2) [010001111] rm[6..3] [000] */
THUMB_BX, /* bx [010001110] H2[6..6] rm[5..3] SBZ[000] */
- THUMB_CMN, /* cmn [0100001011] rm[5..3] rd[2..0] */
+ THUMB_CMN_RR, /* cmn [0100001011] rm[5..3] rd[2..0] */
THUMB_CMP_RI8, /* cmp(1) [00101] rn[10..8] imm_8[7..0] */
THUMB_CMP_RR, /* cmp(2) [0100001010] rm[5..3] rd[2..0] */
THUMB_CMP_LH, /* cmp(3) [01000101] H12[01] rm[5..3] rd[2..0] */
THUMB_CMP_HL, /* cmp(3) [01000110] H12[10] rm[5..3] rd[2..0] */
THUMB_CMP_HH, /* cmp(3) [01000111] H12[11] rm[5..3] rd[2..0] */
- THUMB_EOR, /* eor [0100000001] rm[5..3] rd[2..0] */
+ THUMB_EOR_RR, /* eor [0100000001] rm[5..3] rd[2..0] */
THUMB_LDMIA, /* ldmia [11001] rn[10..8] reglist [7..0] */
THUMB_LDR_RRI5, /* ldr(1) [01101] imm_5[10..6] rn[5..3] rd[2..0] */
THUMB_LDR_RRR, /* ldr(2) [0101100] rm[8..6] rn[5..3] rd[2..0] */
@@ -208,10 +303,10 @@
THUMB_LDRH_RRR, /* ldrh(2) [0101101] rm[8..6] rn[5..3] rd[2..0] */
THUMB_LDRSB_RRR, /* ldrsb [0101011] rm[8..6] rn[5..3] rd[2..0] */
THUMB_LDRSH_RRR, /* ldrsh [0101111] rm[8..6] rn[5..3] rd[2..0] */
- THUMB_LSL, /* lsl(1) [00000] imm_5[10..6] rm[5..3] rd[2..0] */
- THUMB_LSLV, /* lsl(2) [0100000010] rs[5..3] rd[2..0] */
- THUMB_LSR, /* lsr(1) [00001] imm_5[10..6] rm[5..3] rd[2..0] */
- THUMB_LSRV, /* lsr(2) [0100000011] rs[5..3] rd[2..0] */
+ THUMB_LSL_RRI5, /* lsl(1) [00000] imm_5[10..6] rm[5..3] rd[2..0] */
+ THUMB_LSL_RR, /* lsl(2) [0100000010] rs[5..3] rd[2..0] */
+ THUMB_LSR_RRI5, /* lsr(1) [00001] imm_5[10..6] rm[5..3] rd[2..0] */
+ THUMB_LSR_RR, /* lsr(2) [0100000011] rs[5..3] rd[2..0] */
THUMB_MOV_IMM, /* mov(1) [00100] rd[10..8] imm_8[7..0] */
THUMB_MOV_RR, /* mov(2) [0001110000] rn[5..3] rd[2..0] */
THUMB_MOV_RR_H2H, /* mov(3) [01000111] H12[11] rm[5..3] rd[2..0] */
@@ -223,7 +318,7 @@
THUMB_ORR, /* orr [0100001100] rm[5..3] rd[2..0] */
THUMB_POP, /* pop [1011110] r[8..8] rl[7..0] */
THUMB_PUSH, /* push [1011010] r[8..8] rl[7..0] */
- THUMB_ROR, /* ror [0100000111] rs[5..3] rd[2..0] */
+ THUMB_ROR_RR, /* ror [0100000111] rs[5..3] rd[2..0] */
THUMB_SBC, /* sbc [0100000110] rm[5..3] rd[2..0] */
THUMB_STMIA, /* stmia [11000] rn[10..8] reglist [7.. 0] */
THUMB_STR_RRI5, /* str(1) [01100] imm_5[10..6] rn[5..3] rd[2..0] */
@@ -291,32 +386,208 @@
rn[19..16] rt[15..12] [1100] imm[7..0]*/
THUMB2_LDR_RRI8_PREDEC, /* ldr(Imm,T4) rd,[rn,#-imm8] [111110000101]
rn[19..16] rt[15..12] [1100] imm[7..0]*/
- THUMB2_CBNZ, /* cbnz rd,<label> [101110] i [1] imm5[7..3]
+ THUMB2_CBNZ, /* cbnz rd,<label> [101110] i [1] imm5[7..3]
rn[2..0] */
- THUMB2_CBZ, /* cbn rd,<label> [101100] i [1] imm5[7..3]
+ THUMB2_CBZ, /* cbn rd,<label> [101100] i [1] imm5[7..3]
rn[2..0] */
- THUMB2_ADD_RRI12, /* add rd, rn, #imm12 [11110] i [100000] rn[19..16]
+ THUMB2_ADD_RRI12, /* add rd, rn, #imm12 [11110] i [100000] rn[19..16]
[0] imm3[14..12] rd[11..8] imm8[7..0] */
- THUMB2_MOV_RR, /* mov rd, rm [11101010010011110000] rd[11..8]
+ THUMB2_MOV_RR, /* mov rd, rm [11101010010011110000] rd[11..8]
[0000] rm[3..0] */
- THUMB2_VMOVS, /* vmov.f32 vd, vm [111011101] D [110000]
+ THUMB2_VMOVS, /* vmov.f32 vd, vm [111011101] D [110000]
vd[15..12] 101001] M [0] vm[3..0] */
- THUMB2_VMOVD, /* vmov.f64 vd, vm [111011101] D [110000]
+ THUMB2_VMOVD, /* vmov.f64 vd, vm [111011101] D [110000]
vd[15..12] 101101] M [0] vm[3..0] */
+ THUMB2_LDMIA, /* ldmia [111010001001[ rn[19..16] mask[15..0] */
+ THUMB2_STMIA, /* stmia [111010001000[ rn[19..16] mask[15..0] */
+ THUMB2_ADD_RRR, /* add [111010110000] rn[19..16] [0000] rd[11..8]
+ [0000] rm[3..0] */
+ THUMB2_SUB_RRR, /* sub [111010111010] rn[19..16] [0000] rd[11..8]
+ [0000] rm[3..0] */
+ THUMB2_SBC_RRR, /* sbc [111010110110] rn[19..16] [0000] rd[11..8]
+ [0000] rm[3..0] */
+ THUMB2_CMP_RR, /* cmp [111010111011] rn[19..16] [0000] [1111]
+ [0000] rm[3..0] */
+ THUMB2_SUB_RRI12, /* sub rd, rn, #imm12 [11110] i [01010] rn[19..16]
+ [0] imm3[14..12] rd[11..8] imm8[7..0] */
+ THUMB2_MVN_IMM_SHIFT, /* mov(T2) rd, #<const> [11110] i [00011011110]
+ imm3 rd[11..8] imm8 */
+ THUMB2_SEL, /* sel rd, rn, rm [111110101010] rn[19-16] rd[11-8]
+ rm[3-0] */
+ THUMB2_UBFX, /* ubfx rd,rn,#lsb,#width [111100111100] rn[19..16]
+ [0] imm3[14-12] rd[11-8] w[4-0] */
+ THUMB2_SBFX, /* ubfx rd,rn,#lsb,#width [111100110100] rn[19..16]
+ [0] imm3[14-12] rd[11-8] w[4-0] */
+ THUMB2_LDR_RRR, /* ldr rt,[rn,rm,LSL #imm] [111110000101] rn[19-16]
+ rt[15-12] [000000] imm[5-4] rm[3-0] */
+ THUMB2_LDRH_RRR, /* ldrh rt,[rn,rm,LSL #imm] [111110000101] rn[19-16]
+ rt[15-12] [000000] imm[5-4] rm[3-0] */
+ THUMB2_LDRSH_RRR, /* ldrsh rt,[rn,rm,LSL #imm] [111110000101] rn[19-16]
+ rt[15-12] [000000] imm[5-4] rm[3-0] */
+ THUMB2_LDRB_RRR, /* ldrb rt,[rn,rm,LSL #imm] [111110000101] rn[19-16]
+ rt[15-12] [000000] imm[5-4] rm[3-0] */
+ THUMB2_LDRSB_RRR, /* ldrsb rt,[rn,rm,LSL #imm] [111110000101] rn[19-16]
+ rt[15-12] [000000] imm[5-4] rm[3-0] */
+ THUMB2_STR_RRR, /* str rt,[rn,rm,LSL #imm] [111110000100] rn[19-16]
+ rt[15-12] [000000] imm[5-4] rm[3-0] */
+ THUMB2_STRH_RRR, /* str rt,[rn,rm,LSL #imm] [111110000010] rn[19-16]
+ rt[15-12] [000000] imm[5-4] rm[3-0] */
+ THUMB2_STRB_RRR, /* str rt,[rn,rm,LSL #imm] [111110000000] rn[19-16]
+ rt[15-12] [000000] imm[5-4] rm[3-0] */
+ THUMB2_LDRH_RRI12, /* ldrh rt,[rn,#imm12] [111110001011]
+ rt[15..12] rn[19..16] imm12[11..0] */
+ THUMB2_LDRSH_RRI12, /* ldrsh rt,[rn,#imm12] [111110011011]
+ rt[15..12] rn[19..16] imm12[11..0] */
+ THUMB2_LDRB_RRI12, /* ldrb rt,[rn,#imm12] [111110001001]
+ rt[15..12] rn[19..16] imm12[11..0] */
+ THUMB2_LDRSB_RRI12, /* ldrsb rt,[rn,#imm12] [111110011001]
+ rt[15..12] rn[19..16] imm12[11..0] */
+ THUMB2_STRH_RRI12, /* strh rt,[rn,#imm12] [111110001010]
+ rt[15..12] rn[19..16] imm12[11..0] */
+ THUMB2_STRB_RRI12, /* strb rt,[rn,#imm12] [111110001000]
+ rt[15..12] rn[19..16] imm12[11..0] */
+ THUMB2_POP, /* pop [1110100010111101] list[15-0]*/
+ THUMB2_PUSH, /* push [1110100010101101] list[15-0]*/
+ THUMB2_CMP_RI8, /* cmp rn, #<const> [11110] i [011011] rn[19-16] [0]
+ imm3 [1111] imm8[7..0] */
+ THUMB2_ADC_RRR, /* adc [111010110101] rn[19..16] [0000] rd[11..8]
+ [0000] rm[3..0] */
+ THUMB2_AND_RRR, /* and [111010100000] rn[19..16] [0000] rd[11..8]
+ [0000] rm[3..0] */
+ THUMB2_BIC_RRR, /* bic [111010100010] rn[19..16] [0000] rd[11..8]
+ [0000] rm[3..0] */
+ THUMB2_CMN_RR, /* cmn [111010110001] rn[19..16] [0000] [1111]
+ [0000] rm[3..0] */
+ THUMB2_EOR_RRR, /* eor [111010101000] rn[19..16] [0000] rd[11..8]
+ [0000] rm[3..0] */
+ THUMB2_MUL_RRR, /* mul [111110110000] rn[19..16] [1111] rd[11..8]
+ [0000] rm[3..0] */
+ THUMB2_MVN_RR, /* mvn [11101010011011110] rd[11-8] [0000]
+ rm[3..0] */
+ THUMB2_RSUB_RRI8, /* rsub [111100011100] rn[19..16] [0000] rd[11..8]
+ imm8[7..0] */
+ THUMB2_NEG_RR, /* actually rsub rd, rn, #0 */
+ THUMB2_ORR_RRR, /* orr [111010100100] rn[19..16] [0000] rd[11..8]
+ [0000] rm[3..0] */
+ THUMB2_TST_RR, /* tst [111010100001] rn[19..16] [0000] [1111]
+ [0000] rm[3..0] */
+ THUMB2_LSL_RRR, /* lsl [111110100000] rn[19..16] [1111] rd[11..8]
+ [0000] rm[3..0] */
+ THUMB2_LSR_RRR, /* lsr [111110100010] rn[19..16] [1111] rd[11..8]
+ [0000] rm[3..0] */
+ THUMB2_ASR_RRR, /* asr [111110100100] rn[19..16] [1111] rd[11..8]
+ [0000] rm[3..0] */
+ THUMB2_ROR_RRR, /* ror [111110100110] rn[19..16] [1111] rd[11..8]
+ [0000] rm[3..0] */
+ THUMB2_LSL_RRI5, /* lsl [11101010010011110] imm[14.12] rd[11..8]
+ [00] rm[3..0] */
+ THUMB2_LSR_RRI5, /* lsr [11101010010011110] imm[14.12] rd[11..8]
+ [01] rm[3..0] */
+ THUMB2_ASR_RRI5, /* asr [11101010010011110] imm[14.12] rd[11..8]
+ [10] rm[3..0] */
+ THUMB2_ROR_RRI5, /* ror [11101010010011110] imm[14.12] rd[11..8]
+ [11] rm[3..0] */
+ THUMB2_BIC_RRI8, /* bic [111100000010] rn[19..16] [0] imm3
+ rd[11..8] imm8 */
+ THUMB2_AND_RRI8, /* bic [111100000000] rn[19..16] [0] imm3
+ rd[11..8] imm8 */
+ THUMB2_ORR_RRI8, /* orr [111100000100] rn[19..16] [0] imm3
+ rd[11..8] imm8 */
+ THUMB2_EOR_RRI8, /* eor [111100001000] rn[19..16] [0] imm3
+ rd[11..8] imm8 */
+ THUMB2_ADD_RRI8, /* add [111100001000] rn[19..16] [0] imm3
+ rd[11..8] imm8 */
+ THUMB2_ADC_RRI8, /* adc [111100010101] rn[19..16] [0] imm3
+ rd[11..8] imm8 */
+ THUMB2_SUB_RRI8, /* sub [111100011011] rn[19..16] [0] imm3
+ rd[11..8] imm8 */
+ THUMB2_SBC_RRI8, /* sbc [111100010111] rn[19..16] [0] imm3
+ rd[11..8] imm8 */
+ THUMB2_IT, /* it [10111111] firstcond[7-4] mask[3-0] */
+ THUMB2_FMSTAT, /* fmstat [11101110111100011111101000010000] */
+ THUMB2_VCMPD, /* vcmp [111011101] D [11011] rd[15-12] [1011]
+ E [1] M [0] rm[3-0] */
+ THUMB2_VCMPS, /* vcmp [111011101] D [11010] rd[15-12] [1011]
+ E [1] M [0] rm[3-0] */
+ THUMB2_LDR_PC_REL12, /* ldr rd,[pc,#imm12] [1111100011011111] rt[15-12]
+ imm12[11-0] */
+ THUMB2_B_COND, /* b<c> [1110] S cond[25-22] imm6[21-16] [10]
+ J1 [0] J2 imm11[10..0] */
+ THUMB2_VMOVD_RR, /* vmov [111011101] D [110000] vd[15-12 [101101]
+ M [0] vm[3-0] */
+ THUMB2_VMOVS_RR, /* vmov [111011101] D [110000] vd[15-12 [101001]
+ M [0] vm[3-0] */
+ THUMB2_FMRS, /* vmov [111011100000] vn[19-16] rt[15-12] [1010]
+ N [0010000] */
+ THUMB2_FMSR, /* vmov [111011100001] vn[19-16] rt[15-12] [1010]
+ N [0010000] */
+ THUMB2_FMRRD, /* vmov [111011000100] rt2[19-16] rt[15-12]
+ [101100] M [1] vm[3-0] */
+ THUMB2_FMDRR, /* vmov [111011000101] rt2[19-16] rt[15-12]
+ [101100] M [1] vm[3-0] */
+
ARM_LAST,
} ArmOpCode;
/* Bit flags describing the behavior of each native opcode */
typedef enum ArmOpFeatureFlags {
- IS_BRANCH = 1 << 1,
- CLOBBER_DEST = 1 << 2,
- CLOBBER_SRC1 = 1 << 3,
- NO_OPERAND = 1 << 4,
- IS_UNARY_OP = 1 << 5,
- IS_BINARY_OP = 1 << 6,
- IS_TERTIARY_OP = 1 << 7,
+ kIsBranch = 0,
+ kRegDef0,
+ kRegDef1,
+ kRegDefSP,
+ kRegDefLR,
+ kRegDefList0,
+ kRegDefList1,
+ kRegUse0,
+ kRegUse1,
+ kRegUse2,
+ kRegUseSP,
+ kRegUsePC,
+ kRegUseList0,
+ kRegUseList1,
+ kNoOperand,
+ kIsUnaryOp,
+ kIsBinaryOp,
+ kIsTertiaryOp,
+ kIsQuadOp,
+ kIsIT,
+ kSetsCCodes,
+ kUsesCCodes,
} ArmOpFeatureFlags;
+#define IS_BRANCH (1 << kIsBranch)
+#define REG_DEF0 (1 << kRegDef0)
+#define REG_DEF1 (1 << kRegDef1)
+#define REG_DEF_SP (1 << kRegDefSP)
+#define REG_DEF_LR (1 << kRegDefLR)
+#define REG_DEF_LIST0 (1 << kRegDefList0)
+#define REG_DEF_LIST1 (1 << kRegDefList1)
+#define REG_USE0 (1 << kRegUse0)
+#define REG_USE1 (1 << kRegUse1)
+#define REG_USE2 (1 << kRegUse2)
+#define REG_USE_SP (1 << kRegUseSP)
+#define REG_USE_PC (1 << kRegUsePC)
+#define REG_USE_LIST0 (1 << kRegUseList0)
+#define REG_USE_LIST1 (1 << kRegUseList1)
+#define NO_OPERAND (1 << kNoOperand)
+#define IS_UNARY_OP (1 << kIsUnaryOp)
+#define IS_BINARY_OP (1 << kIsBinaryOp)
+#define IS_TERTIARY_OP (1 << kIsTertiaryOp)
+#define IS_QUAD_OP (1 << kIsQuadOp)
+#define IS_IT (1 << kIsIT)
+#define SETS_CCODES (1 << kSetsCCodes)
+#define USES_CCODES (1 << kUsesCCodes)
+
+/* Common combo register usage patterns */
+#define REG_USE01 (REG_USE0 | REG_USE1)
+#define REG_USE012 (REG_USE01 | REG_USE2)
+#define REG_USE12 (REG_USE1 | REG_USE2)
+#define REG_DEF0_USE0 (REG_DEF0 | REG_USE0)
+#define REG_DEF0_USE1 (REG_DEF0 | REG_USE1)
+#define REG_DEF0_USE01 (REG_DEF0 | REG_USE01)
+#define REG_DEF0_USE12 (REG_DEF0 | REG_USE12)
+#define REG_DEF01_USE2 (REG_DEF0 | REG_DEF1 | REG_USE2)
+
/* Instruction assembly fieldLoc kind */
typedef enum ArmEncodingKind {
UNUSED,
@@ -327,6 +598,11 @@
IMM16, /* Zero-extended immediate using [26,19..16,14..12,7..0] */
IMM6, /* Encoded branch target using [9,7..3]0 */
IMM12, /* Zero-extended immediate using [26,14..12,7..0] */
+ SHIFT, /* Shift descriptor, [14..12,7..4] */
+ LSB, /* least significant bit using [14..12][7..6] */
+ BWIDTH, /* bit-field width, encoded as width-1 */
+ SHIFT5, /* Shift count, [14..12,7..6] */
+ BROFFSET, /* Signed extended [26,11,13,21-16,10-0]:0 */
} ArmEncodingKind;
/* Struct used to define the snippet positions for each Thumb opcode */
@@ -336,7 +612,7 @@
ArmEncodingKind kind;
int end; /* end for BITBLT, 1-bit slice end for FP regs */
int start; /* start for BITBLT, 4-bit slice end for FP regs */
- } fieldLoc[3];
+ } fieldLoc[4];
ArmOpCode opCode;
int flags;
char *name;
@@ -349,15 +625,27 @@
/*
* Each instance of this struct holds a pseudo or real LIR instruction:
* - pesudo ones (eg labels and marks) and will be discarded by the assembler.
- * - real ones will e assembled into Thumb instructions.
+ * - real ones will be assembled into Thumb instructions.
+ *
+ * Machine resources are encoded into a 64-bit vector, where the encodings are
+ * as following:
+ * - [ 0..15]: general purpose registers including PC, SP, and LR
+ * - [16..47]: floating-point registers where d0 is expanded to s[01] and s0
+ * starts at bit 16
+ * - [48]: IT block
+ * - [49]: integer condition code
+ * - [50]: floatint-point status word
*/
typedef struct ArmLIR {
LIR generic;
ArmOpCode opCode;
- int operands[3]; // [0..2] = [dest, src1, src2]
+ int operands[4]; // [0..3] = [dest, src1, src2, extra]
bool isNop; // LIR is optimized away
int age; // default is 0, set lazily by the optimizer
int size; // 16-bit unit size (1 for thumb, 1 or 2 for thumb2)
+ int aliasInfo; // For Dalvik register access disambiguation
+ u8 useMask; // Resource mask for use
+ u8 defMask; // Resource mask for def
} ArmLIR;
/* Chain cell for predicted method invocation */
@@ -392,4 +680,6 @@
#define CHAIN_CELL_OFFSET_TAG 0xcdab
+ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc);
+
#endif /* _DALVIK_VM_COMPILER_CODEGEN_ARM_ARMLIR_H */
diff --git a/vm/compiler/codegen/arm/Assemble.c b/vm/compiler/codegen/arm/Assemble.c
index ea133e7..e386fac 100644
--- a/vm/compiler/codegen/arm/Assemble.c
+++ b/vm/compiler/codegen/arm/Assemble.c
@@ -39,9 +39,9 @@
* fmt: for pretty-prining
*/
#define ENCODING_MAP(opcode, skeleton, k0, ds, de, k1, s1s, s1e, k2, s2s, s2e, \
- operands, name, fmt, size) \
- {skeleton, {{k0, ds, de}, {k1, s1s, s1e}, {k2, s2s, s2e}}, \
- opcode, operands, name, fmt, size}
+ k3, k3s, k3e, flags, name, fmt, size) \
+ {skeleton, {{k0, ds, de}, {k1, s1s, s1e}, {k2, s2s, s2e}, \
+ {k3, k3s, k3e}}, opcode, flags, name, fmt, size}
/* Instruction dump string format keys: !pf, where "!" is the start
* of the key, "p" is which numeric operand to use and "f" is the
@@ -51,11 +51,11 @@
* 0 -> operands[0] (dest)
* 1 -> operands[1] (src1)
* 2 -> operands[2] (src2)
+ * 3 -> operands[3] (extra)
*
* [f]ormats:
* h -> 4-digit hex
* d -> decimal
- * D -> decimal+8 (used to convert 3-bit regnum field to high reg)
* E -> decimal*4
* F -> decimal*2
* c -> branch condition (beq, bne, etc.)
@@ -66,436 +66,711 @@
* s -> single precision floating point register
* S -> double precision floating point register
* m -> Thumb2 modified immediate
+ * n -> complimented Thumb2 modified immediate
* M -> Thumb2 16-bit zero-extended immediate
+ * b -> 4-digit binary
*
* [!] escape. To insert "!", use "!!"
*/
/* NOTE: must be kept in sync with enum ArmOpcode from ArmLIR.h */
ArmEncodingMap EncodingMap[ARM_LAST] = {
ENCODING_MAP(ARM_16BIT_DATA, 0x0000,
- BITBLT, 15, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ BITBLT, 15, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
IS_UNARY_OP,
"data", "0x!0h(!0d)", 1),
- ENCODING_MAP(THUMB_ADC, 0x4140,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "adc", "r!0d, r!1d", 1),
+ ENCODING_MAP(THUMB_ADC_RR, 0x4140,
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES | USES_CCODES,
+ "adcs", "r!0d, r!1d", 1),
ENCODING_MAP(THUMB_ADD_RRI3, 0x1c00,
- BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
- IS_TERTIARY_OP | CLOBBER_DEST,
- "add", "r!0d, r!1d, #!2d", 1),
+ BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+ "adds", "r!0d, r!1d, #!2d", 1),
ENCODING_MAP(THUMB_ADD_RI8, 0x3000,
- BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "add", "r!0d, r!0d, #!1d", 1),
+ BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE0 | SETS_CCODES,
+ "adds", "r!0d, r!0d, #!1d", 1),
ENCODING_MAP(THUMB_ADD_RRR, 0x1800,
- BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
- IS_TERTIARY_OP | CLOBBER_DEST,
- "add", "r!0d, r!1d, r!2d", 1),
+ BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE12 | SETS_CCODES,
+ "adds", "r!0d, r!1d, r!2d", 1),
ENCODING_MAP(THUMB_ADD_RR_LH, 0x4440,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "add",
- "r!0d, r!1d", 1),
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE01,
+ "add", "r!0d, r!1d", 1),
ENCODING_MAP(THUMB_ADD_RR_HL, 0x4480,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE01,
"add", "r!0d, r!1d", 1),
ENCODING_MAP(THUMB_ADD_RR_HH, 0x44c0,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE01,
"add", "r!0d, r!1d", 1),
ENCODING_MAP(THUMB_ADD_PC_REL, 0xa000,
- BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
- IS_TERTIARY_OP | CLOBBER_DEST,
+ BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_TERTIARY_OP | IS_BRANCH,
"add", "r!0d, pc, #!1E", 1),
ENCODING_MAP(THUMB_ADD_SP_REL, 0xa800,
- BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "add", "r!0d, sp, #!1E", 1),
+ BITBLT, 10, 8, UNUSED, -1, -1, BITBLT, 7, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF_SP | REG_USE_SP,
+ "add", "r!0d, sp, #!2E", 1),
ENCODING_MAP(THUMB_ADD_SPI7, 0xb000,
- BITBLT, 6, 0, UNUSED, -1, -1, UNUSED, -1, -1,
- IS_UNARY_OP | CLOBBER_DEST,
+ BITBLT, 6, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_UNARY_OP | REG_DEF_SP | REG_USE_SP,
"add", "sp, #!0d*4", 1),
ENCODING_MAP(THUMB_AND_RR, 0x4000,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "and", "r!0d, r!1d", 1),
- ENCODING_MAP(THUMB_ASR, 0x1000,
- BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
- IS_TERTIARY_OP | CLOBBER_DEST,
- "asr", "r!0d, r!1d, #!2d", 1),
- ENCODING_MAP(THUMB_ASRV, 0x4100,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "asr", "r!0d, r!1d", 1),
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
+ "ands", "r!0d, r!1d", 1),
+ ENCODING_MAP(THUMB_ASR_RRI5, 0x1000,
+ BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+ "asrs", "r!0d, r!1d, #!2d", 1),
+ ENCODING_MAP(THUMB_ASR_RR, 0x4100,
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
+ "asrs", "r!0d, r!1d", 1),
ENCODING_MAP(THUMB_B_COND, 0xd000,
- BITBLT, 7, 0, BITBLT, 11, 8, UNUSED, -1, -1,
- IS_BINARY_OP | IS_BRANCH,
- "!1c", "!0t", 1),
+ BITBLT, 7, 0, BITBLT, 11, 8, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | IS_BRANCH | USES_CCODES,
+ "b!1c", "!0t", 1),
ENCODING_MAP(THUMB_B_UNCOND, 0xe000,
- BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
NO_OPERAND | IS_BRANCH,
"b", "!0t", 1),
- ENCODING_MAP(THUMB_BIC, 0x4380,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "bic", "r!0d, r!1d", 1),
+ ENCODING_MAP(THUMB_BIC_RR, 0x4380,
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
+ "bics", "r!0d, r!1d", 1),
ENCODING_MAP(THUMB_BKPT, 0xbe00,
- BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
IS_UNARY_OP | IS_BRANCH,
"bkpt", "!0d", 1),
ENCODING_MAP(THUMB_BLX_1, 0xf000,
- BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1,
- IS_BINARY_OP | IS_BRANCH,
+ BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | IS_BRANCH | REG_DEF_LR,
"blx_1", "!0u", 1),
ENCODING_MAP(THUMB_BLX_2, 0xe800,
- BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1,
- IS_BINARY_OP | IS_BRANCH,
+ BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | IS_BRANCH | REG_DEF_LR,
"blx_2", "!0v", 1),
ENCODING_MAP(THUMB_BL_1, 0xf000,
- BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1,
- IS_UNARY_OP | IS_BRANCH,
+ BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_UNARY_OP | IS_BRANCH | REG_DEF_LR,
"bl_1", "!0u", 1),
ENCODING_MAP(THUMB_BL_2, 0xf800,
- BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1,
- IS_UNARY_OP | IS_BRANCH,
+ BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_UNARY_OP | IS_BRANCH | REG_DEF_LR,
"bl_2", "!0v", 1),
ENCODING_MAP(THUMB_BLX_R, 0x4780,
- BITBLT, 6, 3, UNUSED, -1, -1, UNUSED, -1, -1,
- IS_UNARY_OP | IS_BRANCH,
+ BITBLT, 6, 3, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_UNARY_OP | REG_USE0 | IS_BRANCH | REG_DEF_LR,
"blx", "r!0d", 1),
ENCODING_MAP(THUMB_BX, 0x4700,
- BITBLT, 6, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ BITBLT, 6, 3, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
IS_UNARY_OP | IS_BRANCH,
"bx", "r!0d", 1),
- ENCODING_MAP(THUMB_CMN, 0x42c0,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP,
+ ENCODING_MAP(THUMB_CMN_RR, 0x42c0,
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_USE01 | SETS_CCODES,
"cmn", "r!0d, r!1d", 1),
ENCODING_MAP(THUMB_CMP_RI8, 0x2800,
- BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
- IS_BINARY_OP,
+ BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_USE0 | SETS_CCODES,
"cmp", "r!0d, #!1d", 1),
ENCODING_MAP(THUMB_CMP_RR, 0x4280,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP,
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_USE01 | SETS_CCODES,
"cmp", "r!0d, r!1d", 1),
ENCODING_MAP(THUMB_CMP_LH, 0x4540,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP,
- "cmp", "r!0d, r!1D", 1),
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_USE01 | SETS_CCODES,
+ "cmp", "r!0d, r!1d", 1),
ENCODING_MAP(THUMB_CMP_HL, 0x4580,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP,
- "cmp", "r!0D, r!1d", 1),
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_USE01 | SETS_CCODES,
+ "cmp", "r!0d, r!1d", 1),
ENCODING_MAP(THUMB_CMP_HH, 0x45c0,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP,
- "cmp", "r!0D, r!1D", 1),
- ENCODING_MAP(THUMB_EOR, 0x4040,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "eor", "r!0d, r!1d", 1),
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_USE01 | SETS_CCODES,
+ "cmp", "r!0d, r!1d", 1),
+ ENCODING_MAP(THUMB_EOR_RR, 0x4040,
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
+ "eors", "r!0d, r!1d", 1),
ENCODING_MAP(THUMB_LDMIA, 0xc800,
- BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST | CLOBBER_SRC1,
+ BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE0 | REG_DEF_LIST1,
"ldmia", "r!0d!!, <!1R>", 1),
ENCODING_MAP(THUMB_LDR_RRI5, 0x6800,
- BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
- IS_TERTIARY_OP | CLOBBER_DEST,
+ BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1,
"ldr", "r!0d, [r!1d, #!2E]", 1),
ENCODING_MAP(THUMB_LDR_RRR, 0x5800,
- BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
- IS_TERTIARY_OP | CLOBBER_DEST,
+ BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE12,
"ldr", "r!0d, [r!1d, r!2d]", 1),
ENCODING_MAP(THUMB_LDR_PC_REL, 0x4800,
- BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
- IS_TERTIARY_OP | CLOBBER_DEST,
+ BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0 | REG_USE_PC,
"ldr", "r!0d, [pc, #!1E]", 1),
ENCODING_MAP(THUMB_LDR_SP_REL, 0x9800,
- BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "ldr", "r!0d, [sp, #!1E]", 1),
+ BITBLT, 10, 8, UNUSED, -1, -1, BITBLT, 7, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0 | REG_USE_SP,
+ "ldr", "r!0d, [sp, #!2E]", 1),
ENCODING_MAP(THUMB_LDRB_RRI5, 0x7800,
- BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
- IS_TERTIARY_OP | CLOBBER_DEST,
+ BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1,
"ldrb", "r!0d, [r!1d, #2d]", 1),
ENCODING_MAP(THUMB_LDRB_RRR, 0x5c00,
- BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
- IS_TERTIARY_OP | CLOBBER_DEST,
+ BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE12,
"ldrb", "r!0d, [r!1d, r!2d]", 1),
ENCODING_MAP(THUMB_LDRH_RRI5, 0x8800,
- BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
- IS_TERTIARY_OP | CLOBBER_DEST,
+ BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1,
"ldrh", "r!0d, [r!1d, #!2F]", 1),
ENCODING_MAP(THUMB_LDRH_RRR, 0x5a00,
- BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
- IS_TERTIARY_OP | CLOBBER_DEST,
+ BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE12,
"ldrh", "r!0d, [r!1d, r!2d]", 1),
ENCODING_MAP(THUMB_LDRSB_RRR, 0x5600,
- BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
- IS_TERTIARY_OP | CLOBBER_DEST,
+ BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE12,
"ldrsb", "r!0d, [r!1d, r!2d]", 1),
ENCODING_MAP(THUMB_LDRSH_RRR, 0x5e00,
- BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
- IS_TERTIARY_OP | CLOBBER_DEST,
+ BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE12,
"ldrsh", "r!0d, [r!1d, r!2d]", 1),
- ENCODING_MAP(THUMB_LSL, 0x0000,
- BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
- IS_TERTIARY_OP | CLOBBER_DEST,
- "lsl", "r!0d, r!1d, #!2d", 1),
- ENCODING_MAP(THUMB_LSLV, 0x4080,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "lsl", "r!0d, r!1d", 1),
- ENCODING_MAP(THUMB_LSR, 0x0800,
- BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
- IS_TERTIARY_OP | CLOBBER_DEST,
- "lsr", "r!0d, r!1d, #!2d", 1),
- ENCODING_MAP(THUMB_LSRV, 0x40c0,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "lsr", "r!0d, r!1d", 1),
+ ENCODING_MAP(THUMB_LSL_RRI5, 0x0000,
+ BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+ "lsls", "r!0d, r!1d, #!2d", 1),
+ ENCODING_MAP(THUMB_LSL_RR, 0x4080,
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
+ "lsls", "r!0d, r!1d", 1),
+ ENCODING_MAP(THUMB_LSR_RRI5, 0x0800,
+ BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+ "lsrs", "r!0d, r!1d, #!2d", 1),
+ ENCODING_MAP(THUMB_LSR_RR, 0x40c0,
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
+ "lsrs", "r!0d, r!1d", 1),
ENCODING_MAP(THUMB_MOV_IMM, 0x2000,
- BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "mov", "r!0d, #!1d", 1),
+ BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0 | SETS_CCODES,
+ "movs", "r!0d, #!1d", 1),
ENCODING_MAP(THUMB_MOV_RR, 0x1c00,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "mov", "r!0d, r!1d", 1),
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+ "movs", "r!0d, r!1d", 1),
ENCODING_MAP(THUMB_MOV_RR_H2H, 0x46c0,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "mov", "r!0D, r!1D", 1),
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE1,
+ "mov", "r!0d, r!1d", 1),
ENCODING_MAP(THUMB_MOV_RR_H2L, 0x4640,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "mov", "r!0d, r!1D", 1),
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE1,
+ "mov", "r!0d, r!1d", 1),
ENCODING_MAP(THUMB_MOV_RR_L2H, 0x4680,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "mov", "r!0D, r!1d", 1),
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE1,
+ "mov", "r!0d, r!1d", 1),
ENCODING_MAP(THUMB_MUL, 0x4340,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "mul", "r!0d, r!1d", 1),
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
+ "muls", "r!0d, r!1d", 1),
ENCODING_MAP(THUMB_MVN, 0x43c0,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "mvn", "r!0d, r!1d", 1),
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+ "mvns", "r!0d, r!1d", 1),
ENCODING_MAP(THUMB_NEG, 0x4240,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "neg", "r!0d, r!1d", 1),
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+ "negs", "r!0d, r!1d", 1),
ENCODING_MAP(THUMB_ORR, 0x4300,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "orr", "r!0d, r!1d", 1),
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
+ "orrs", "r!0d, r!1d", 1),
ENCODING_MAP(THUMB_POP, 0xbc00,
- BITBLT, 8, 0, UNUSED, -1, -1, UNUSED, -1, -1,
- IS_UNARY_OP,
+ BITBLT, 8, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_DEF_LIST0,
"pop", "<!0R>", 1),
ENCODING_MAP(THUMB_PUSH, 0xb400,
- BITBLT, 8, 0, UNUSED, -1, -1, UNUSED, -1, -1,
- IS_UNARY_OP,
+ BITBLT, 8, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_USE_LIST0,
"push", "<!0R>", 1),
- ENCODING_MAP(THUMB_ROR, 0x41c0,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "ror", "r!0d, r!1d", 1),
+ ENCODING_MAP(THUMB_ROR_RR, 0x41c0,
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE01 | SETS_CCODES,
+ "rors", "r!0d, r!1d", 1),
ENCODING_MAP(THUMB_SBC, 0x4180,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "sbc", "r!0d, r!1d", 1),
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE01 | USES_CCODES | SETS_CCODES,
+ "sbcs", "r!0d, r!1d", 1),
ENCODING_MAP(THUMB_STMIA, 0xc000,
- BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_SRC1,
+ BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0 | REG_USE0 | REG_USE_LIST1,
"stmia", "r!0d!!, <!1R>", 1),
ENCODING_MAP(THUMB_STR_RRI5, 0x6000,
- BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
- IS_TERTIARY_OP,
+ BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_USE01,
"str", "r!0d, [r!1d, #!2E]", 1),
ENCODING_MAP(THUMB_STR_RRR, 0x5000,
- BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
- IS_TERTIARY_OP,
+ BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_USE012,
"str", "r!0d, [r!1d, r!2d]", 1),
ENCODING_MAP(THUMB_STR_SP_REL, 0x9000,
- BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
- IS_BINARY_OP,
- "str", "r!0d, [sp, #!1E]", 1),
+ BITBLT, 10, 8, UNUSED, -1, -1, BITBLT, 7, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_USE0 | REG_USE_SP,
+ "str", "r!0d, [sp, #!2E]", 1),
ENCODING_MAP(THUMB_STRB_RRI5, 0x7000,
- BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
- IS_TERTIARY_OP,
+ BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_USE01,
"strb", "r!0d, [r!1d, #!2d]", 1),
ENCODING_MAP(THUMB_STRB_RRR, 0x5400,
- BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
- IS_TERTIARY_OP,
+ BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_USE012,
"strb", "r!0d, [r!1d, r!2d]", 1),
ENCODING_MAP(THUMB_STRH_RRI5, 0x8000,
- BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
- IS_TERTIARY_OP,
+ BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_USE01,
"strh", "r!0d, [r!1d, #!2F]", 1),
ENCODING_MAP(THUMB_STRH_RRR, 0x5200,
- BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
- IS_TERTIARY_OP,
+ BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_USE012,
"strh", "r!0d, [r!1d, r!2d]", 1),
ENCODING_MAP(THUMB_SUB_RRI3, 0x1e00,
- BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
- IS_TERTIARY_OP | CLOBBER_DEST,
- "sub", "r!0d, r!1d, #!2d]", 1),
+ BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+ "subs", "r!0d, r!1d, #!2d]", 1),
ENCODING_MAP(THUMB_SUB_RI8, 0x3800,
- BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "sub", "r!0d, #!1d", 1),
+ BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE0 | SETS_CCODES,
+ "subs", "r!0d, #!1d", 1),
ENCODING_MAP(THUMB_SUB_RRR, 0x1a00,
- BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
- IS_TERTIARY_OP | CLOBBER_DEST,
- "sub", "r!0d, r!1d, r!2d", 1),
+ BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE12 | SETS_CCODES,
+ "subs", "r!0d, r!1d, r!2d", 1),
ENCODING_MAP(THUMB_SUB_SPI7, 0xb080,
- BITBLT, 6, 0, UNUSED, -1, -1, UNUSED, -1, -1,
- IS_UNARY_OP | CLOBBER_DEST,
+ BITBLT, 6, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_UNARY_OP | REG_DEF_SP | REG_USE_SP,
"sub", "sp, #!0d", 1),
ENCODING_MAP(THUMB_SWI, 0xdf00,
- BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ BITBLT, 7, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
IS_UNARY_OP | IS_BRANCH,
"swi", "!0d", 1),
ENCODING_MAP(THUMB_TST, 0x4200,
- BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
- IS_UNARY_OP,
+ BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_UNARY_OP | REG_USE01 | SETS_CCODES,
"tst", "r!0d, r!1d", 1),
ENCODING_MAP(THUMB2_VLDRS, 0xed900a00,
- SFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0,
- IS_TERTIARY_OP | CLOBBER_DEST,
+ SFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1,
"vldr", "!0s, [r!1d, #!2E]", 2),
ENCODING_MAP(THUMB2_VLDRD, 0xed900b00,
- DFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0,
- IS_TERTIARY_OP | CLOBBER_DEST,
+ DFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1,
"vldr", "!0S, [r!1d, #!2E]", 2),
ENCODING_MAP(THUMB2_VMULS, 0xee200a00,
- SFP, 22, 12, SFP, 7, 16, SFP, 5, 0,
- IS_TERTIARY_OP | CLOBBER_DEST,
+ SFP, 22, 12, SFP, 7, 16, SFP, 5, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE12,
"vmuls", "!0s, !1s, !2s", 2),
ENCODING_MAP(THUMB2_VMULD, 0xee200b00,
- DFP, 22, 12, DFP, 7, 16, DFP, 5, 0,
- IS_TERTIARY_OP | CLOBBER_DEST,
+ DFP, 22, 12, DFP, 7, 16, DFP, 5, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE12,
"vmuld", "!0S, !1S, !2S", 2),
ENCODING_MAP(THUMB2_VSTRS, 0xed800a00,
- SFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0,
- IS_TERTIARY_OP,
+ SFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_USE01,
"vstr", "!0s, [r!1d, #!2E]", 2),
ENCODING_MAP(THUMB2_VSTRD, 0xed800b00,
- DFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0,
- IS_TERTIARY_OP,
+ DFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_USE01,
"vstr", "!0S, [r!1d, #!2E]", 2),
ENCODING_MAP(THUMB2_VSUBS, 0xee300a40,
- SFP, 22, 12, SFP, 7, 16, SFP, 5, 0,
- IS_TERTIARY_OP | CLOBBER_DEST,
+ SFP, 22, 12, SFP, 7, 16, SFP, 5, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE12,
"vsub", "!0s, !1s, !2s", 2),
ENCODING_MAP(THUMB2_VSUBD, 0xee300b40,
- DFP, 22, 12, DFP, 7, 16, DFP, 5, 0,
- IS_TERTIARY_OP | CLOBBER_DEST,
+ DFP, 22, 12, DFP, 7, 16, DFP, 5, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE12,
"vsub", "!0S, !1S, !2S", 2),
ENCODING_MAP(THUMB2_VADDS, 0xee300a00,
- SFP, 22, 12, SFP, 7, 16, SFP, 5, 0,
- IS_TERTIARY_OP | CLOBBER_DEST,
+ SFP, 22, 12, SFP, 7, 16, SFP, 5, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE12,
"vadd", "!0s, !1s, !2s", 2),
ENCODING_MAP(THUMB2_VADDD, 0xee300b00,
- DFP, 22, 12, DFP, 7, 16, DFP, 5, 0,
- IS_TERTIARY_OP | CLOBBER_DEST,
+ DFP, 22, 12, DFP, 7, 16, DFP, 5, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE12,
"vadd", "!0S, !1S, !2S", 2),
ENCODING_MAP(THUMB2_VDIVS, 0xee800a00,
- SFP, 22, 12, SFP, 7, 16, SFP, 5, 0,
- IS_TERTIARY_OP | CLOBBER_DEST,
+ SFP, 22, 12, SFP, 7, 16, SFP, 5, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE12,
"vdivs", "!0s, !1s, !2s", 2),
ENCODING_MAP(THUMB2_VDIVD, 0xee800b00,
- DFP, 22, 12, DFP, 7, 16, DFP, 5, 0,
- IS_TERTIARY_OP | CLOBBER_DEST,
- "vdivs", "!0S, !1S, !2S", 2),
+ DFP, 22, 12, DFP, 7, 16, DFP, 5, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE12,
+ "vdivd", "!0S, !1S, !2S", 2),
ENCODING_MAP(THUMB2_VCVTIF, 0xeeb80ac0,
- SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
+ SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE1,
"vcvt.f32", "!0s, !1s", 2),
ENCODING_MAP(THUMB2_VCVTID, 0xeeb80bc0,
- DFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
+ DFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE1,
"vcvt.f64", "!0S, !1s", 2),
ENCODING_MAP(THUMB2_VCVTFI, 0xeebd0ac0,
- SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
+ SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE1,
"vcvt.s32.f32 ", "!0s, !1s", 2),
ENCODING_MAP(THUMB2_VCVTDI, 0xeebd0bc0,
- SFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
+ SFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE1,
"vcvt.s32.f64 ", "!0s, !1S", 2),
ENCODING_MAP(THUMB2_VCVTFD, 0xeeb70ac0,
- DFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
+ DFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE1,
"vcvt.f64.f32 ", "!0S, !1s", 2),
ENCODING_MAP(THUMB2_VCVTDF, 0xeeb70bc0,
- SFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
+ SFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE1,
"vcvt.f32.f64 ", "!0s, !1S", 2),
ENCODING_MAP(THUMB2_VSQRTS, 0xeeb10ac0,
- SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
+ SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE1,
"vsqrt.f32 ", "!0s, !1s", 2),
ENCODING_MAP(THUMB2_VSQRTD, 0xeeb10bc0,
- DFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
+ DFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE1,
"vsqrt.f64 ", "!0S, !1S", 2),
- ENCODING_MAP(THUMB2_MOV_IMM_SHIFT, 0xf04f0000,
- BITBLT, 11, 8, MODIMM, -1, -1, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
+ ENCODING_MAP(THUMB2_MOV_IMM_SHIFT, 0xf04f0000, /* no setflags encoding */
+ BITBLT, 11, 8, MODIMM, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0,
"mov", "r!0d, #!1m", 2),
ENCODING_MAP(THUMB2_MOV_IMM16, 0xf2400000,
- BITBLT, 11, 8, IMM16, -1, -1, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
+ BITBLT, 11, 8, IMM16, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0,
"mov", "r!0d, #!1M", 2),
ENCODING_MAP(THUMB2_STR_RRI12, 0xf8c00000,
- BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0,
- IS_TERTIARY_OP,
+ BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_USE01,
"str", "r!0d,[r!1d, #!2d", 2),
ENCODING_MAP(THUMB2_LDR_RRI12, 0xf8d00000,
- BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0,
- IS_TERTIARY_OP | CLOBBER_DEST,
+ BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1,
"ldr", "r!0d,[r!1d, #!2d", 2),
ENCODING_MAP(THUMB2_STR_RRI8_PREDEC, 0xf8400c00,
- BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 8, 0,
- IS_TERTIARY_OP,
+ BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 8, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_USE01,
"str", "r!0d,[r!1d, #-!2d]", 2),
ENCODING_MAP(THUMB2_LDR_RRI8_PREDEC, 0xf8500c00,
- BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 8, 0,
- IS_TERTIARY_OP | CLOBBER_DEST,
+ BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 8, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1,
"ldr", "r!0d,[r!1d, #-!2d]", 2),
- ENCODING_MAP(THUMB2_CBNZ, 0xb900,
- BITBLT, 2, 0, IMM6, -1, -1, UNUSED, -1, -1,
- IS_BINARY_OP,
+ ENCODING_MAP(THUMB2_CBNZ, 0xb900, /* Note: does not affect flags */
+ BITBLT, 2, 0, IMM6, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_USE0 | IS_BRANCH,
"cbnz", "r!0d,!1t", 1),
- ENCODING_MAP(THUMB2_CBZ, 0xb100,
- BITBLT, 2, 0, IMM6, -1, -1, UNUSED, -1, -1,
- IS_BINARY_OP,
+ ENCODING_MAP(THUMB2_CBZ, 0xb100, /* Note: does not affect flags */
+ BITBLT, 2, 0, IMM6, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_USE0 | IS_BRANCH,
"cbz", "r!0d,!1t", 1),
- ENCODING_MAP(THUMB2_ADD_RRI12, 0xf1000000,
- BITBLT, 11, 8, BITBLT, 19, 16, IMM12, -1, -1,
- IS_TERTIARY_OP | CLOBBER_DEST,
+ ENCODING_MAP(THUMB2_ADD_RRI12, 0xf2000000,
+ BITBLT, 11, 8, BITBLT, 19, 16, IMM12, -1, -1, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1,/* Note: doesn't affect flags */
"add", "r!0d,r!1d,#!2d", 2),
- ENCODING_MAP(THUMB2_MOV_RR, 0xea4f0000,
- BITBLT, 11, 8, BITBLT, 3, 0, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
+ ENCODING_MAP(THUMB2_MOV_RR, 0xea4f0000, /* no setflags encoding */
+ BITBLT, 11, 8, BITBLT, 3, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE1,
"mov", "r!0d, r!1d", 2),
ENCODING_MAP(THUMB2_VMOVS, 0xeeb00a40,
- SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "vmov.f32 ", "!0s, !1s", 2),
+ SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE1,
+ "vmov.f32 ", " !0s, !1s", 2),
ENCODING_MAP(THUMB2_VMOVD, 0xeeb00b40,
- DFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1,
- IS_BINARY_OP | CLOBBER_DEST,
- "vmov.f64 ", "!0s, !1s", 2),
+ DFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE1,
+ "vmov.f64 ", " !0S, !1S", 2),
+ ENCODING_MAP(THUMB2_LDMIA, 0xe8900000,
+ BITBLT, 19, 16, BITBLT, 15, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE0 | REG_DEF_LIST1,
+ "ldmia", "r!0d!!, <!1R>", 2),
+ ENCODING_MAP(THUMB2_STMIA, 0xe8800000,
+ BITBLT, 19, 16, BITBLT, 15, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE0 | REG_USE_LIST1,
+ "stmia", "r!0d!!, <!1R>", 2),
+ ENCODING_MAP(THUMB2_ADD_RRR, 0xeb100000, /* setflags encoding */
+ BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1,
+ IS_QUAD_OP | REG_DEF0_USE12 | SETS_CCODES,
+ "adds", "r!0d, r!1d, r!2d", 2),
+ ENCODING_MAP(THUMB2_SUB_RRR, 0xebb00000, /* setflags enconding */
+ BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1,
+ IS_QUAD_OP | REG_DEF0_USE12 | SETS_CCODES,
+ "subs", "r!0d, r!1d, r!2d", 2),
+ ENCODING_MAP(THUMB2_SBC_RRR, 0xeb700000, /* setflags encoding */
+ BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1,
+ IS_QUAD_OP | REG_DEF0_USE12 | USES_CCODES | SETS_CCODES,
+ "sbcs", "r!0d, r!1d, r!2d", 2),
+ ENCODING_MAP(THUMB2_CMP_RR, 0xebb00f00,
+ BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_USE01 | SETS_CCODES,
+ "cmp", "r!0d, r!1d", 2),
+ ENCODING_MAP(THUMB2_SUB_RRI12, 0xf2a00000,
+ BITBLT, 11, 8, BITBLT, 19, 16, IMM12, -1, -1, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1,/* Note: doesn't affect flags */
+ "sub", "r!0d,r!1d,#!2d", 2),
+ ENCODING_MAP(THUMB2_MVN_IMM_SHIFT, 0xf06f0000, /* no setflags encoding */
+ BITBLT, 11, 8, MODIMM, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0,
+ "mvn", "r!0d, #!1n", 2),
+ ENCODING_MAP(THUMB2_SEL, 0xfaa0f080,
+ BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE12 | USES_CCODES,
+ "sel", "r!0d, r!1d, r!2d", 2),
+ ENCODING_MAP(THUMB2_UBFX, 0xf3c00000,
+ BITBLT, 11, 8, BITBLT, 19, 16, LSB, -1, -1, BWIDTH, 4, 0,
+ IS_QUAD_OP | REG_DEF0_USE1,
+ "ubfx", "r!0d, r!1d, #!2d, #!3d", 2),
+ ENCODING_MAP(THUMB2_SBFX, 0xf3400000,
+ BITBLT, 11, 8, BITBLT, 19, 16, LSB, -1, -1, BWIDTH, 4, 0,
+ IS_QUAD_OP | REG_DEF0_USE1,
+ "sbfx", "r!0d, r!1d, #!2d, #!3d", 2),
+ ENCODING_MAP(THUMB2_LDR_RRR, 0xf8500000,
+ BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 3, 0, BITBLT, 5, 4,
+ IS_QUAD_OP | REG_DEF0_USE12,
+ "ldr", "r!0d,[r!1d, r!2d, LSL #!3d]", 2),
+ ENCODING_MAP(THUMB2_LDRH_RRR, 0xf8300000,
+ BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 3, 0, BITBLT, 5, 4,
+ IS_QUAD_OP | REG_DEF0_USE12,
+ "ldrh", "r!0d,[r!1d, r!2d, LSL #!3d]", 2),
+ ENCODING_MAP(THUMB2_LDRSH_RRR, 0xf9300000,
+ BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 3, 0, BITBLT, 5, 4,
+ IS_QUAD_OP | REG_DEF0_USE12,
+ "ldrsh", "r!0d,[r!1d, r!2d, LSL #!3d]", 2),
+ ENCODING_MAP(THUMB2_LDRB_RRR, 0xf8100000,
+ BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 3, 0, BITBLT, 5, 4,
+ IS_QUAD_OP | REG_DEF0_USE12,
+ "ldrb", "r!0d,[r!1d, r!2d, LSL #!3d]", 2),
+ ENCODING_MAP(THUMB2_LDRSB_RRR, 0xf9100000,
+ BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 3, 0, BITBLT, 5, 4,
+ IS_QUAD_OP | REG_DEF0_USE12,
+ "ldrsb", "r!0d,[r!1d, r!2d, LSL #!3d]", 2),
+ ENCODING_MAP(THUMB2_STR_RRR, 0xf8400000,
+ BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 3, 0, BITBLT, 5, 4,
+ IS_QUAD_OP | REG_USE012,
+ "str", "r!0d,[r!1d, r!2d, LSL #!3d]", 2),
+ ENCODING_MAP(THUMB2_STRH_RRR, 0xf8200000,
+ BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 3, 0, BITBLT, 5, 4,
+ IS_QUAD_OP | REG_USE012,
+ "strh", "r!0d,[r!1d, r!2d, LSL #!3d]", 2),
+ ENCODING_MAP(THUMB2_STRB_RRR, 0xf8000000,
+ BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 3, 0, BITBLT, 5, 4,
+ IS_QUAD_OP | REG_USE012,
+ "strb", "r!0d,[r!1d, r!2d, LSL #!3d]", 2),
+ ENCODING_MAP(THUMB2_LDRH_RRI12, 0xf8b00000,
+ BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1,
+ "ldrh", "r!0d,[r!1d, #!2d", 2),
+ ENCODING_MAP(THUMB2_LDRSH_RRI12, 0xf9b00000,
+ BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1,
+ "ldrsh", "r!0d,[r!1d, #!2d", 2),
+ ENCODING_MAP(THUMB2_LDRB_RRI12, 0xf8900000,
+ BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1,
+ "ldrb", "r!0d,[r!1d, #!2d", 2),
+ ENCODING_MAP(THUMB2_LDRSB_RRI12, 0xf9900000,
+ BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1,
+ "ldrsb", "r!0d,[r!1d, #!2d", 2),
+ ENCODING_MAP(THUMB2_STRH_RRI12, 0xf8a00000,
+ BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_USE01,
+ "strh", "r!0d,[r!1d, #!2d", 2),
+ ENCODING_MAP(THUMB2_STRB_RRI12, 0xf8800000,
+ BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_USE01,
+ "strb", "r!0d,[r!1d, #!2d", 2),
+ ENCODING_MAP(THUMB2_POP, 0xe8bd0000,
+ BITBLT, 15, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_DEF_LIST0,
+ "pop", "<!0R>", 2),
+ ENCODING_MAP(THUMB2_PUSH, 0xe8ad0000,
+ BITBLT, 15, 0, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_UNARY_OP | REG_DEF_SP | REG_USE_SP | REG_USE_LIST0,
+ "push", "<!0R>", 2),
+ ENCODING_MAP(THUMB2_CMP_RI8, 0xf1b00f00,
+ BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_USE0 | SETS_CCODES,
+ "cmp", "r!0d, #!1m", 2),
+ ENCODING_MAP(THUMB2_ADC_RRR, 0xeb500000, /* setflags encoding */
+ BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1,
+ IS_QUAD_OP | REG_DEF0_USE12 | SETS_CCODES,
+ "acds", "r!0d, r!1d, r!2d, shift !3d", 2),
+ ENCODING_MAP(THUMB2_AND_RRR, 0xea000000,
+ BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1,
+ IS_QUAD_OP | REG_DEF0_USE12,
+ "and", "r!0d, r!1d, r!2d, shift !3d", 2),
+ ENCODING_MAP(THUMB2_BIC_RRR, 0xea200000,
+ BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1,
+ IS_QUAD_OP | REG_DEF0_USE12,
+ "bic", "r!0d, r!1d, r!2d, shift !3d", 2),
+ ENCODING_MAP(THUMB2_CMN_RR, 0xeb000000,
+ BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+ "cmn", "r!0d, r!1d, shift !2d", 2),
+ ENCODING_MAP(THUMB2_EOR_RRR, 0xea800000,
+ BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1,
+ IS_QUAD_OP | REG_DEF0_USE12,
+ "eor", "r!0d, r!1d, r!2d, shift !3d", 2),
+ ENCODING_MAP(THUMB2_MUL_RRR, 0xfb00f000,
+ BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE12,
+ "mul", "r!0d, r!1d, r!2d", 2),
+ ENCODING_MAP(THUMB2_MVN_RR, 0xea6f0000,
+ BITBLT, 11, 8, BITBLT, 3, 0, SHIFT, -1, -1, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1,
+ "mvn", "r!0d, r!1d, shift !2d", 2),
+ ENCODING_MAP(THUMB2_RSUB_RRI8, 0xf1d00000,
+ BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+ "rsb", "r!0d,r!1d,#!2m", 2),
+ ENCODING_MAP(THUMB2_NEG_RR, 0xf1d00000, /* instance of rsub */
+ BITBLT, 11, 8, BITBLT, 19, 16, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+ "neg", "r!0d,r!1d", 2),
+ ENCODING_MAP(THUMB2_ORR_RRR, 0xea400000,
+ BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1,
+ IS_QUAD_OP | REG_DEF0_USE12,
+ "orr", "r!0d, r!1d, r!2d, shift !3d", 2),
+ ENCODING_MAP(THUMB2_TST_RR, 0xea100f00,
+ BITBLT, 19, 16, BITBLT, 3, 0, SHIFT, -1, -1, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_USE01 | SETS_CCODES,
+ "tst", "r!0d, r!1d, shift !2d", 2),
+ ENCODING_MAP(THUMB2_LSL_RRR, 0xfa00f000,
+ BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE12,
+ "lsl", "r!0d, r!1d, r!2d", 2),
+ ENCODING_MAP(THUMB2_LSR_RRR, 0xfa20f000,
+ BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE12,
+ "lsr", "r!0d, r!1d, r!2d", 2),
+ ENCODING_MAP(THUMB2_ASR_RRR, 0xfa40f000,
+ BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE12,
+ "asr", "r!0d, r!1d, r!2d", 2),
+ ENCODING_MAP(THUMB2_ROR_RRR, 0xfa60f000,
+ BITBLT, 11, 8, BITBLT, 19, 16, BITBLT, 3, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE12,
+ "ror", "r!0d, r!1d, r!2d", 2),
+ ENCODING_MAP(THUMB2_LSL_RRI5, 0xea4f0000,
+ BITBLT, 11, 8, BITBLT, 3, 0, SHIFT5, -1, -1, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1,
+ "lsl", "r!0d, r!1d, #!2d", 2),
+ ENCODING_MAP(THUMB2_LSR_RRI5, 0xea4f0010,
+ BITBLT, 11, 8, BITBLT, 3, 0, SHIFT5, -1, -1, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1,
+ "lsr", "r!0d, r!1d, #!2d", 2),
+ ENCODING_MAP(THUMB2_ASR_RRI5, 0xea4f0020,
+ BITBLT, 11, 8, BITBLT, 3, 0, SHIFT5, -1, -1, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1,
+ "asr", "r!0d, r!1d, #!2d", 2),
+ ENCODING_MAP(THUMB2_ROR_RRI5, 0xea4f0030,
+ BITBLT, 11, 8, BITBLT, 3, 0, SHIFT5, -1, -1, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1,
+ "ror", "r!0d, r!1d, #!2d", 2),
+ ENCODING_MAP(THUMB2_BIC_RRI8, 0xf0200000,
+ BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1,
+ "bic", "r!0d, r!1d, #!2m", 2),
+ ENCODING_MAP(THUMB2_AND_RRI8, 0xf0000000,
+ BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1,
+ "and", "r!0d, r!1d, #!2m", 2),
+ ENCODING_MAP(THUMB2_ORR_RRI8, 0xf0400000,
+ BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1,
+ "orr", "r!0d, r!1d, #!2m", 2),
+ ENCODING_MAP(THUMB2_EOR_RRI8, 0xf0800000,
+ BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1,
+ "eor", "r!0d, r!1d, #!2m", 2),
+ ENCODING_MAP(THUMB2_ADD_RRI8, 0xf1100000,
+ BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+ "adds", "r!0d, r!1d, #!2m", 2),
+ ENCODING_MAP(THUMB2_ADC_RRI8, 0xf1500000,
+ BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES | USES_CCODES,
+ "adcs", "r!0d, r!1d, #!2m", 2),
+ ENCODING_MAP(THUMB2_SUB_RRI8, 0xf1b00000,
+ BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES,
+ "subs", "r!0d, r!1d, #!2m", 2),
+ ENCODING_MAP(THUMB2_SBC_RRI8, 0xf1700000,
+ BITBLT, 11, 8, BITBLT, 19, 16, MODIMM, -1, -1, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE1 | SETS_CCODES | USES_CCODES,
+ "sbcs", "r!0d, r!1d, #!2m", 2),
+ ENCODING_MAP(THUMB2_IT, 0xbf00,
+ BITBLT, 7, 4, BITBLT, 3, 0, MODIMM, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | IS_IT | USES_CCODES,
+ "it:!1b", "!0c", 1),
+ ENCODING_MAP(THUMB2_FMSTAT, 0xeef1fa10,
+ UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1, UNUSED, -1, -1,
+ NO_OPERAND | SETS_CCODES,
+ "fmstat", "", 2),
+ ENCODING_MAP(THUMB2_VCMPD, 0xeeb40b40,
+ DFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_USE01,
+ "vcmp.f64", "!0S, !1S", 2),
+ ENCODING_MAP(THUMB2_VCMPS, 0xeeb40a40,
+ SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_USE01,
+ "vcmp.f32", "!0s, !1s", 2),
+ ENCODING_MAP(THUMB2_LDR_PC_REL12, 0xf8df0000,
+ BITBLT, 15, 12, BITBLT, 11, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0 | REG_USE_PC,
+ "ldr", "r!0d,[rpc, #!1d", 2),
+ ENCODING_MAP(THUMB2_B_COND, 0xf0008000,
+ BROFFSET, -1, -1, BITBLT, 25, 22, UNUSED, -1, -1,
+ UNUSED, -1, -1,
+ IS_BINARY_OP | IS_BRANCH | USES_CCODES,
+ "b!1c", "!0t", 2),
+ ENCODING_MAP(THUMB2_VMOVD_RR, 0xeeb00b40,
+ DFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE1,
+ "vmov.f64", "!0S, !1S", 2),
+ ENCODING_MAP(THUMB2_VMOVS_RR, 0xeeb00a40,
+ SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE1,
+ "vmov.f32", "!0S, !1S", 2),
+ ENCODING_MAP(THUMB2_FMRS, 0xee100a10,
+ BITBLT, 15, 12, SFP, 8, 16, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE1,
+ "fmrs", "r!0d, !1s", 2),
+ ENCODING_MAP(THUMB2_FMSR, 0xee000a10,
+ SFP, 8, 16, BITBLT, 15, 12, UNUSED, -1, -1, UNUSED, -1, -1,
+ IS_BINARY_OP | REG_DEF0_USE1,
+ "fmsr", "!0s, r!1d", 2),
+ ENCODING_MAP(THUMB2_FMRRD, 0xec500b10,
+ BITBLT, 15, 12, BITBLT, 19, 16, DFP, 5, 0, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF01_USE2,
+ "fmrrd", "r!0d, r!1d, !2S", 2),
+ ENCODING_MAP(THUMB2_FMDRR, 0xec400b10,
+ DFP, 5, 0, BITBLT, 15, 12, BITBLT, 19, 16, UNUSED, -1, -1,
+ IS_TERTIARY_OP | REG_DEF0_USE12,
+ "fmdrr", "!0S, r!1d, r!2d", 2),
};
-#define PADDING_MOV_R0_R0 0x1C00
+/*
+ * The fake NOP of moving r0 to r0 actually will incur data stalls if r0 is
+ * not ready. Since r5 (rFP) is not updated often, it is less likely to
+ * generate unnecessary stall cycles.
+ */
+#define PADDING_MOV_R5_R5 0x1C2D
/* Write the numbers in the literal pool to the codegen stream */
static void installDataContent(CompilationUnit *cUnit)
@@ -530,7 +805,7 @@
if ((lir->opCode == ARM_PSEUDO_ALIGN4) &&
/* 1 means padding is needed */
(lir->operands[0] == 1)) {
- *bufferAddr++ = PADDING_MOV_R0_R0;
+ *bufferAddr++ = PADDING_MOV_R5_R5;
}
continue;
}
@@ -540,6 +815,7 @@
}
if (lir->opCode == THUMB_LDR_PC_REL ||
+ lir->opCode == THUMB2_LDR_PC_REL12 ||
lir->opCode == THUMB_ADD_PC_REL) {
ArmLIR *lirTarget = (ArmLIR *) lir->generic.target;
intptr_t pc = (lir->generic.offset + 4) & ~3;
@@ -554,25 +830,34 @@
LOGE("PC-rel distance is not multiples of 4: %d\n", delta);
dvmAbort();
}
- if (delta > 1023) {
+ if ((lir->opCode == THUMB2_LDR_PC_REL12) && (delta > 4091)) {
+ return true;
+ } else if (delta > 1020) {
return true;
}
- lir->operands[1] = delta >> 2;
+ lir->operands[1] = (lir->opCode == THUMB2_LDR_PC_REL12) ?
+ delta : delta >> 2;
} else if (lir->opCode == THUMB2_CBNZ || lir->opCode == THUMB2_CBZ) {
ArmLIR *targetLIR = (ArmLIR *) lir->generic.target;
intptr_t pc = lir->generic.offset + 4;
intptr_t target = targetLIR->generic.offset;
int delta = target - pc;
if (delta > 126 || delta < 0) {
+ /*
+ * TODO: allow multiple kinds of assembler failure to allow
+ * change of code patterns when things don't fit.
+ */
return true;
+ } else {
+ lir->operands[1] = delta >> 1;
}
- lir->operands[1] = delta >> 1;
- } else if (lir->opCode == THUMB_B_COND) {
+ } else if (lir->opCode == THUMB_B_COND ||
+ lir->opCode == THUMB2_B_COND) {
ArmLIR *targetLIR = (ArmLIR *) lir->generic.target;
intptr_t pc = lir->generic.offset + 4;
intptr_t target = targetLIR->generic.offset;
int delta = target - pc;
- if (delta > 254 || delta < -256) {
+ if ((lir->opCode == THUMB_B_COND) && (delta > 254 || delta < -256)) {
return true;
}
lir->operands[0] = delta >> 1;
@@ -606,51 +891,81 @@
ArmEncodingMap *encoder = &EncodingMap[lir->opCode];
u4 bits = encoder->skeleton;
int i;
- for (i = 0; i < 3; i++) {
+ for (i = 0; i < 4; i++) {
+ u4 operand;
u4 value;
+ operand = lir->operands[i];
switch(encoder->fieldLoc[i].kind) {
case UNUSED:
break;
+ case BROFFSET:
+ value = ((operand & 0x80000) >> 19) << 26;
+ value |= ((operand & 0x40000) >> 18) << 11;
+ value |= ((operand & 0x20000) >> 17) << 13;
+ value |= ((operand & 0x1f800) >> 11) << 16;
+ value |= (operand & 0x007ff);
+ break;
+ case SHIFT5:
+ value = ((operand & 0x1c) >> 2) << 12;
+ value |= (operand & 0x03) << 6;
+ bits |= value;
+ break;
+ case SHIFT:
+ value = ((operand & 0x70) >> 4) << 12;
+ value |= (operand & 0x0f) << 4;
+ bits |= value;
+ break;
+ case BWIDTH:
+ value = operand - 1;
+ bits |= value;
+ break;
+ case LSB:
+ value = ((operand & 0x1c) >> 2) << 12;
+ value |= (operand & 0x03) << 6;
+ bits |= value;
+ break;
case IMM6:
- value = ((lir->operands[i] & 0x20) >> 5) << 9;
- value |= (lir->operands[i] & 0x1f) << 3;
+ value = ((operand & 0x20) >> 5) << 9;
+ value |= (operand & 0x1f) << 3;
bits |= value;
break;
case BITBLT:
- value = (lir->operands[i] << encoder->fieldLoc[i].start) &
+ value = (operand << encoder->fieldLoc[i].start) &
((1 << (encoder->fieldLoc[i].end + 1)) - 1);
bits |= value;
break;
- case DFP:
+ case DFP: {
+ int regName = (operand & FP_REG_MASK) >> 1;
/* Snag the 1-bit slice and position it */
- value = ((lir->operands[i] & 0x10) >> 4) <<
+ value = ((regName & 0x10) >> 4) <<
encoder->fieldLoc[i].end;
/* Extract and position the 4-bit slice */
- value |= (lir->operands[i] & 0x0f) <<
+ value |= (regName & 0x0f) <<
encoder->fieldLoc[i].start;
bits |= value;
break;
+ }
case SFP:
/* Snag the 1-bit slice and position it */
- value = (lir->operands[i] & 0x1) <<
+ value = (operand & 0x1) <<
encoder->fieldLoc[i].end;
/* Extract and position the 4-bit slice */
- value |= ((lir->operands[i] & 0x1e) >> 1) <<
+ value |= ((operand & 0x1e) >> 1) <<
encoder->fieldLoc[i].start;
bits |= value;
break;
case IMM12:
case MODIMM:
- value = ((lir->operands[i] & 0x800) >> 11) << 26;
- value |= ((lir->operands[i] & 0x700) >> 8) << 12;
- value |= lir->operands[i] & 0x0ff;
+ value = ((operand & 0x800) >> 11) << 26;
+ value |= ((operand & 0x700) >> 8) << 12;
+ value |= operand & 0x0ff;
bits |= value;
break;
case IMM16:
- value = ((lir->operands[i] & 0x0800) >> 11) << 26;
- value |= ((lir->operands[i] & 0xf000) >> 12) << 16;
- value |= ((lir->operands[i] & 0x0700) >> 8) << 12;
- value |= lir->operands[i] & 0x0ff;
+ value = ((operand & 0x0800) >> 11) << 26;
+ value |= ((operand & 0xf000) >> 12) << 16;
+ value |= ((operand & 0x0700) >> 8) << 12;
+ value |= operand & 0x0ff;
bits |= value;
break;
default:
@@ -902,6 +1217,12 @@
PredictedChainingCell *cell,
const ClassObject *clazz)
{
+#if defined(WITH_SELF_VERIFICATION)
+ /* Disable chaining and prevent this from triggering again for a while */
+ cell->counter = PREDICTED_CHAIN_COUNTER_AVOID;
+ cacheflush((long) cell, (long) (cell+1), 0);
+ goto done;
+#else
/* Don't come back here for a long time if the method is native */
if (dvmIsNativeMethod(method)) {
cell->counter = PREDICTED_CHAIN_COUNTER_AVOID;
@@ -951,6 +1272,7 @@
/* All done - resume all other threads */
dvmResumeAllThreads(SUSPEND_FOR_JIT);
+#endif
done:
return method;
@@ -1018,6 +1340,17 @@
predChainCell->method = PREDICTED_CHAIN_METHOD_INIT;
predChainCell->counter = PREDICTED_CHAIN_COUNTER_INIT;
break;
+#if defined(WITH_SELF_VERIFICATION)
+ case CHAINING_CELL_BACKWARD_BRANCH:
+ targetOffset = offsetof(InterpState,
+ jitToInterpEntries.dvmJitToBackwardBranch);
+ break;
+#elif defined(WITH_JIT_TUNING)
+ case CHAINING_CELL_BACKWARD_BRANCH:
+ targetOffset = offsetof(InterpState,
+ jitToInterpEntries.dvmJitToInterpNormal);
+ break;
+#endif
default:
dvmAbort();
}
diff --git a/vm/compiler/codegen/arm/Codegen.c b/vm/compiler/codegen/arm/Codegen.c
index 7d127f8..4a85fb2 100644
--- a/vm/compiler/codegen/arm/Codegen.c
+++ b/vm/compiler/codegen/arm/Codegen.c
@@ -24,6 +24,7 @@
* applicable directory below this one.
*/
+#include "compiler/Loop.h"
/* Array holding the entry offset of each template relative to the first one */
static intptr_t templateEntryOffsets[TEMPLATE_LAST_MARK];
@@ -31,10 +32,591 @@
/* Track exercised opcodes */
static int opcodeCoverage[256];
-/*****************************************************************************/
+#if defined(WITH_SELF_VERIFICATION)
+/* Prevent certain opcodes from being jitted */
+static inline bool selfVerificationPuntOps(OpCode op)
+{
+ return (op == OP_MONITOR_ENTER || op == OP_MONITOR_EXIT ||
+ op == OP_NEW_INSTANCE || op == OP_NEW_ARRAY);
+}
/*
- * The following are building blocks to construct low-level IRs with 0 - 3
+ * The following are used to keep compiled loads and stores from modifying
+ * memory during self verification mode.
+ *
+ * Stores do not modify memory. Instead, the address and value pair are stored
+ * into heapSpace. Addresses within heapSpace are unique. For accesses smaller
+ * than a word, the word containing the address is loaded first before being
+ * updated.
+ *
+ * Loads check heapSpace first and return data from there if an entry exists.
+ * Otherwise, data is loaded from memory as usual.
+ */
+
+/* Decode contents of heapArgSpace to determine addr to load from */
+static void selfVerificationLoadDecode(HeapArgSpace* heapArgSpace, int* addr)
+{
+ int reg = heapArgSpace->regMap & 0xF;
+
+ switch (reg) {
+ case 0:
+ *addr = heapArgSpace->r0;
+ break;
+ case 1:
+ *addr = heapArgSpace->r1;
+ break;
+ case 2:
+ *addr = heapArgSpace->r2;
+ break;
+ case 3:
+ *addr = heapArgSpace->r3;
+ break;
+ default:
+ LOGE("ERROR: bad reg used in selfVerificationLoadDecode: %d", reg);
+ break;
+ }
+}
+
+/* Decode contents of heapArgSpace to determine reg to load into */
+static void selfVerificationLoadDecodeData(HeapArgSpace* heapArgSpace,
+ int data, int reg)
+{
+ switch (reg) {
+ case 0:
+ heapArgSpace->r0 = data;
+ break;
+ case 1:
+ heapArgSpace->r1 = data;
+ break;
+ case 2:
+ heapArgSpace->r2 = data;
+ break;
+ case 3:
+ heapArgSpace->r3 = data;
+ break;
+ default:
+ LOGE("ERROR: bad reg passed to selfVerificationLoadDecodeData: %d",
+ reg);
+ break;
+ }
+}
+
+static void selfVerificationLoad(InterpState* interpState)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowHeap *heapSpacePtr;
+ ShadowSpace *shadowSpace = self->shadowSpace;
+ HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+ int addr, data;
+ selfVerificationLoadDecode(heapArgSpace, &addr);
+
+ for (heapSpacePtr = shadowSpace->heapSpace;
+ heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+ if (heapSpacePtr->addr == addr) {
+ data = heapSpacePtr->data;
+ break;
+ }
+ }
+
+ if (heapSpacePtr == shadowSpace->heapSpaceTail)
+ data = *((unsigned int*) addr);
+
+ int reg = (heapArgSpace->regMap >> 4) & 0xF;
+
+ //LOGD("*** HEAP LOAD: Reg:%d Addr: 0x%x Data: 0x%x", reg, addr, data);
+
+ selfVerificationLoadDecodeData(heapArgSpace, data, reg);
+}
+
+static void selfVerificationLoadByte(InterpState* interpState)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowHeap *heapSpacePtr;
+ ShadowSpace *shadowSpace = self->shadowSpace;
+ HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+ int addr, data;
+ selfVerificationLoadDecode(heapArgSpace, &addr);
+
+ int maskedAddr = addr & 0xFFFFFFFC;
+ int alignment = addr & 0x3;
+
+ for (heapSpacePtr = shadowSpace->heapSpace;
+ heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+ if (heapSpacePtr->addr == maskedAddr) {
+ addr = ((unsigned int) &(heapSpacePtr->data)) | alignment;
+ data = *((unsigned char*) addr);
+ break;
+ }
+ }
+
+ if (heapSpacePtr == shadowSpace->heapSpaceTail)
+ data = *((unsigned char*) addr);
+
+ //LOGD("*** HEAP LOAD BYTE: Addr: 0x%x Data: 0x%x", addr, data);
+
+ int reg = (heapArgSpace->regMap >> 4) & 0xF;
+ selfVerificationLoadDecodeData(heapArgSpace, data, reg);
+}
+
+static void selfVerificationLoadHalfword(InterpState* interpState)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowHeap *heapSpacePtr;
+ ShadowSpace *shadowSpace = self->shadowSpace;
+ HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+ int addr, data;
+ selfVerificationLoadDecode(heapArgSpace, &addr);
+
+ int maskedAddr = addr & 0xFFFFFFFC;
+ int alignment = addr & 0x2;
+
+ for (heapSpacePtr = shadowSpace->heapSpace;
+ heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+ if (heapSpacePtr->addr == maskedAddr) {
+ addr = ((unsigned int) &(heapSpacePtr->data)) | alignment;
+ data = *((unsigned short*) addr);
+ break;
+ }
+ }
+
+ if (heapSpacePtr == shadowSpace->heapSpaceTail)
+ data = *((unsigned short*) addr);
+
+ //LOGD("*** HEAP LOAD HALFWORD: Addr: 0x%x Data: 0x%x", addr, data);
+
+ int reg = (heapArgSpace->regMap >> 4) & 0xF;
+ selfVerificationLoadDecodeData(heapArgSpace, data, reg);
+}
+
+static void selfVerificationLoadSignedByte(InterpState* interpState)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowHeap* heapSpacePtr;
+ ShadowSpace* shadowSpace = self->shadowSpace;
+ HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+ int addr, data;
+ selfVerificationLoadDecode(heapArgSpace, &addr);
+
+ int maskedAddr = addr & 0xFFFFFFFC;
+ int alignment = addr & 0x3;
+
+ for (heapSpacePtr = shadowSpace->heapSpace;
+ heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+ if (heapSpacePtr->addr == maskedAddr) {
+ addr = ((unsigned int) &(heapSpacePtr->data)) | alignment;
+ data = *((signed char*) addr);
+ break;
+ }
+ }
+
+ if (heapSpacePtr == shadowSpace->heapSpaceTail)
+ data = *((signed char*) addr);
+
+ //LOGD("*** HEAP LOAD SIGNED BYTE: Addr: 0x%x Data: 0x%x", addr, data);
+
+ int reg = (heapArgSpace->regMap >> 4) & 0xF;
+ selfVerificationLoadDecodeData(heapArgSpace, data, reg);
+}
+
+static void selfVerificationLoadSignedHalfword(InterpState* interpState)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowHeap* heapSpacePtr;
+ ShadowSpace* shadowSpace = self->shadowSpace;
+ HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+ int addr, data;
+ selfVerificationLoadDecode(heapArgSpace, &addr);
+
+ int maskedAddr = addr & 0xFFFFFFFC;
+ int alignment = addr & 0x2;
+
+ for (heapSpacePtr = shadowSpace->heapSpace;
+ heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+ if (heapSpacePtr->addr == maskedAddr) {
+ addr = ((unsigned int) &(heapSpacePtr->data)) | alignment;
+ data = *((signed short*) addr);
+ break;
+ }
+ }
+
+ if (heapSpacePtr == shadowSpace->heapSpaceTail)
+ data = *((signed short*) addr);
+
+ //LOGD("*** HEAP LOAD SIGNED HALFWORD: Addr: 0x%x Data: 0x%x", addr, data);
+
+ int reg = (heapArgSpace->regMap >> 4) & 0xF;
+ selfVerificationLoadDecodeData(heapArgSpace, data, reg);
+}
+
+static void selfVerificationLoadDoubleword(InterpState* interpState)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowHeap* heapSpacePtr;
+ ShadowSpace* shadowSpace = self->shadowSpace;
+ HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+ int addr;
+ selfVerificationLoadDecode(heapArgSpace, &addr);
+
+ int addr2 = addr+4;
+ unsigned int data = *((unsigned int*) addr);
+ unsigned int data2 = *((unsigned int*) addr2);
+
+ for (heapSpacePtr = shadowSpace->heapSpace;
+ heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+ if (heapSpacePtr->addr == addr) {
+ data = heapSpacePtr->data;
+ } else if (heapSpacePtr->addr == addr2) {
+ data2 = heapSpacePtr->data;
+ }
+ }
+
+ //LOGD("*** HEAP LOAD DOUBLEWORD: Addr: 0x%x Data: 0x%x Data2: 0x%x",
+ // addr, data, data2);
+
+ int reg = (heapArgSpace->regMap >> 4) & 0xF;
+ int reg2 = (heapArgSpace->regMap >> 8) & 0xF;
+ selfVerificationLoadDecodeData(heapArgSpace, data, reg);
+ selfVerificationLoadDecodeData(heapArgSpace, data2, reg2);
+}
+
+/* Decode contents of heapArgSpace to determine arguments to store. */
+static void selfVerificationStoreDecode(HeapArgSpace* heapArgSpace,
+ int* value, int reg)
+{
+ switch (reg) {
+ case 0:
+ *value = heapArgSpace->r0;
+ break;
+ case 1:
+ *value = heapArgSpace->r1;
+ break;
+ case 2:
+ *value = heapArgSpace->r2;
+ break;
+ case 3:
+ *value = heapArgSpace->r3;
+ break;
+ default:
+ LOGE("ERROR: bad reg passed to selfVerificationStoreDecode: %d",
+ reg);
+ break;
+ }
+}
+
+static void selfVerificationStore(InterpState* interpState)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowHeap *heapSpacePtr;
+ ShadowSpace *shadowSpace = self->shadowSpace;
+ HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+ int addr, data;
+ int reg0 = heapArgSpace->regMap & 0xF;
+ int reg1 = (heapArgSpace->regMap >> 4) & 0xF;
+ selfVerificationStoreDecode(heapArgSpace, &addr, reg0);
+ selfVerificationStoreDecode(heapArgSpace, &data, reg1);
+
+ //LOGD("*** HEAP STORE: Addr: 0x%x Data: 0x%x", addr, data);
+
+ for (heapSpacePtr = shadowSpace->heapSpace;
+ heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+ if (heapSpacePtr->addr == addr) break;
+ }
+
+ if (heapSpacePtr == shadowSpace->heapSpaceTail) {
+ heapSpacePtr->addr = addr;
+ shadowSpace->heapSpaceTail++;
+ }
+
+ heapSpacePtr->data = data;
+}
+
+static void selfVerificationStoreByte(InterpState* interpState)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowHeap *heapSpacePtr;
+ ShadowSpace *shadowSpace = self->shadowSpace;
+ HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+ int addr, data;
+ int reg0 = heapArgSpace->regMap & 0xF;
+ int reg1 = (heapArgSpace->regMap >> 4) & 0xF;
+ selfVerificationStoreDecode(heapArgSpace, &addr, reg0);
+ selfVerificationStoreDecode(heapArgSpace, &data, reg1);
+
+ int maskedAddr = addr & 0xFFFFFFFC;
+ int alignment = addr & 0x3;
+
+ //LOGD("*** HEAP STORE BYTE: Addr: 0x%x Data: 0x%x", addr, data);
+
+ for (heapSpacePtr = shadowSpace->heapSpace;
+ heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+ if (heapSpacePtr->addr == maskedAddr) break;
+ }
+
+ if (heapSpacePtr == shadowSpace->heapSpaceTail) {
+ heapSpacePtr->addr = maskedAddr;
+ heapSpacePtr->data = *((unsigned int*) maskedAddr);
+ shadowSpace->heapSpaceTail++;
+ }
+
+ addr = ((unsigned int) &(heapSpacePtr->data)) | alignment;
+ *((unsigned char*) addr) = (char) data;
+
+ //LOGD("*** HEAP STORE BYTE: Addr: 0x%x Final Data: 0x%x",
+ // addr, heapSpacePtr->data);
+}
+
+static void selfVerificationStoreHalfword(InterpState* interpState)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowHeap *heapSpacePtr;
+ ShadowSpace *shadowSpace = self->shadowSpace;
+ HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+ int addr, data;
+ int reg0 = heapArgSpace->regMap & 0xF;
+ int reg1 = (heapArgSpace->regMap >> 4) & 0xF;
+ selfVerificationStoreDecode(heapArgSpace, &addr, reg0);
+ selfVerificationStoreDecode(heapArgSpace, &data, reg1);
+
+ int maskedAddr = addr & 0xFFFFFFFC;
+ int alignment = addr & 0x2;
+
+ //LOGD("*** HEAP STORE HALFWORD: Addr: 0x%x Data: 0x%x", addr, data);
+
+ for (heapSpacePtr = shadowSpace->heapSpace;
+ heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+ if (heapSpacePtr->addr == maskedAddr) break;
+ }
+
+ if (heapSpacePtr == shadowSpace->heapSpaceTail) {
+ heapSpacePtr->addr = maskedAddr;
+ heapSpacePtr->data = *((unsigned int*) maskedAddr);
+ shadowSpace->heapSpaceTail++;
+ }
+
+ addr = ((unsigned int) &(heapSpacePtr->data)) | alignment;
+ *((unsigned short*) addr) = (short) data;
+
+ //LOGD("*** HEAP STORE HALFWORD: Addr: 0x%x Final Data: 0x%x",
+ // addr, heapSpacePtr->data);
+}
+
+static void selfVerificationStoreDoubleword(InterpState* interpState)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowHeap *heapSpacePtr;
+ ShadowSpace *shadowSpace = self->shadowSpace;
+ HeapArgSpace *heapArgSpace = &(interpState->heapArgSpace);
+
+ int addr, data, data2;
+ int reg0 = heapArgSpace->regMap & 0xF;
+ int reg1 = (heapArgSpace->regMap >> 4) & 0xF;
+ int reg2 = (heapArgSpace->regMap >> 8) & 0xF;
+ selfVerificationStoreDecode(heapArgSpace, &addr, reg0);
+ selfVerificationStoreDecode(heapArgSpace, &data, reg1);
+ selfVerificationStoreDecode(heapArgSpace, &data2, reg2);
+
+ int addr2 = addr+4;
+ bool store1 = false, store2 = false;
+
+ //LOGD("*** HEAP STORE DOUBLEWORD: Addr: 0x%x Data: 0x%x, Data2: 0x%x",
+ // addr, data, data2);
+
+ for (heapSpacePtr = shadowSpace->heapSpace;
+ heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+ if (heapSpacePtr->addr == addr) {
+ heapSpacePtr->data = data;
+ store1 = true;
+ } else if (heapSpacePtr->addr == addr2) {
+ heapSpacePtr->data = data2;
+ store2 = true;
+ }
+ }
+
+ if (!store1) {
+ shadowSpace->heapSpaceTail->addr = addr;
+ shadowSpace->heapSpaceTail->data = data;
+ shadowSpace->heapSpaceTail++;
+ }
+ if (!store2) {
+ shadowSpace->heapSpaceTail->addr = addr2;
+ shadowSpace->heapSpaceTail->data = data2;
+ shadowSpace->heapSpaceTail++;
+ }
+}
+
+/* Common wrapper function for all memory operations */
+static void selfVerificationMemOpWrapper(CompilationUnit *cUnit, int regMap,
+ void* funct)
+{
+ int regMask = (1 << r4PC) | (1 << r3) | (1 << r2) | (1 << r1) | (1 << r0);
+
+ /* r7 <- InterpState->heapArgSpace */
+ loadConstant(cUnit, r4PC, offsetof(InterpState, heapArgSpace));
+ newLIR3(cUnit, THUMB_ADD_RRR, r7, rGLUE, r4PC);
+
+ /* Save out values to heapArgSpace */
+ loadConstant(cUnit, r4PC, regMap);
+ newLIR2(cUnit, THUMB_STMIA, r7, regMask);
+
+ /* Pass interpState pointer to function */
+ newLIR2(cUnit, THUMB_MOV_RR, r0, rGLUE);
+
+ /* Set function pointer and branch */
+ loadConstant(cUnit, r1, (int) funct);
+ newLIR1(cUnit, THUMB_BLX_R, r1);
+
+ /* r7 <- InterpState->heapArgSpace */
+ loadConstant(cUnit, r4PC, offsetof(InterpState, heapArgSpace));
+ newLIR3(cUnit, THUMB_ADD_RRR, r7, rGLUE, r4PC);
+
+ /* Restore register state */
+ newLIR2(cUnit, THUMB_LDMIA, r7, regMask);
+}
+#endif
+
+/*
+ * Mark load/store instructions that access Dalvik registers through rFP +
+ * offset.
+ */
+static void annotateDalvikRegAccess(ArmLIR *lir, int regId, bool isLoad)
+{
+ if (isLoad) {
+ lir->useMask |= ENCODE_DALVIK_REG;
+ } else {
+ lir->defMask |= ENCODE_DALVIK_REG;
+ }
+
+ /*
+ * Store the Dalvik register id in aliasInfo. Mark he MSB if it is a 64-bit
+ * access.
+ */
+ lir->aliasInfo = regId;
+ if (DOUBLEREG(lir->operands[0])) {
+ lir->aliasInfo |= 0x80000000;
+ }
+}
+
+/*
+ * Decode the register id and mark the corresponding bit(s).
+ */
+static inline void setupRegMask(u8 *mask, int reg)
+{
+ u8 seed;
+ int shift;
+ int regId = reg & 0x1f;
+
+ /*
+ * Each double register is equal to a pair of single-precision FP registers
+ */
+ seed = DOUBLEREG(reg) ? 3 : 1;
+ /* FP register starts at bit position 16 */
+ shift = FPREG(reg) ? kFPReg0 : 0;
+ /* Expand the double register id into single offset */
+ shift += regId;
+ *mask |= seed << shift;
+}
+
+/*
+ * Set up the proper fields in the resource mask
+ */
+static void setupResourceMasks(ArmLIR *lir)
+{
+ int opCode = lir->opCode;
+ int flags;
+
+ if (opCode <= 0) {
+ lir->useMask = lir->defMask = 0;
+ return;
+ }
+
+ flags = EncodingMap[lir->opCode].flags;
+
+ /* Set up the mask for resources that are updated */
+ if (flags & IS_BRANCH) {
+ lir->defMask |= ENCODE_REG_PC;
+ lir->useMask |= ENCODE_REG_PC;
+ }
+
+ if (flags & REG_DEF0) {
+ setupRegMask(&lir->defMask, lir->operands[0]);
+ }
+
+ if (flags & REG_DEF1) {
+ setupRegMask(&lir->defMask, lir->operands[1]);
+ }
+
+ if (flags & REG_DEF_SP) {
+ lir->defMask |= ENCODE_REG_SP;
+ }
+
+ if (flags & REG_DEF_SP) {
+ lir->defMask |= ENCODE_REG_LR;
+ }
+
+ if (flags & REG_DEF_LIST0) {
+ lir->defMask |= ENCODE_REG_LIST(lir->operands[0]);
+ }
+
+ if (flags & REG_DEF_LIST1) {
+ lir->defMask |= ENCODE_REG_LIST(lir->operands[1]);
+ }
+
+ if (flags & SETS_CCODES) {
+ lir->defMask |= ENCODE_CCODE;
+ }
+
+ /* Conservatively treat the IT block */
+ if (flags & IS_IT) {
+ lir->defMask = ENCODE_ALL;
+ }
+
+ /* Set up the mask for resources that are used */
+ if (flags & IS_BRANCH) {
+ lir->useMask |= ENCODE_REG_PC;
+ }
+
+ if (flags & (REG_USE0 | REG_USE1 | REG_USE2)) {
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ if (flags & (1 << (kRegUse0 + i))) {
+ setupRegMask(&lir->useMask, lir->operands[i]);
+ }
+ }
+ }
+
+ if (flags & REG_USE_PC) {
+ lir->useMask |= ENCODE_REG_PC;
+ }
+
+ if (flags & REG_USE_SP) {
+ lir->useMask |= ENCODE_REG_SP;
+ }
+
+ if (flags & REG_USE_LIST0) {
+ lir->useMask |= ENCODE_REG_LIST(lir->operands[0]);
+ }
+
+ if (flags & REG_USE_LIST1) {
+ lir->useMask |= ENCODE_REG_LIST(lir->operands[1]);
+ }
+
+ if (flags & USES_CCODES) {
+ lir->useMask |= ENCODE_CCODE;
+ }
+}
+
+/*
+ * The following are building blocks to construct low-level IRs with 0 - 4
* operands.
*/
static ArmLIR *newLIR0(CompilationUnit *cUnit, ArmOpCode opCode)
@@ -42,6 +624,7 @@
ArmLIR *insn = dvmCompilerNew(sizeof(ArmLIR), true);
assert(isPseudoOpCode(opCode) || (EncodingMap[opCode].flags & NO_OPERAND));
insn->opCode = opCode;
+ setupResourceMasks(insn);
dvmCompilerAppendLIR(cUnit, (LIR *) insn);
return insn;
}
@@ -53,6 +636,7 @@
assert(isPseudoOpCode(opCode) || (EncodingMap[opCode].flags & IS_UNARY_OP));
insn->opCode = opCode;
insn->operands[0] = dest;
+ setupResourceMasks(insn);
dvmCompilerAppendLIR(cUnit, (LIR *) insn);
return insn;
}
@@ -66,6 +650,7 @@
insn->opCode = opCode;
insn->operands[0] = dest;
insn->operands[1] = src1;
+ setupResourceMasks(insn);
dvmCompilerAppendLIR(cUnit, (LIR *) insn);
return insn;
}
@@ -80,21 +665,46 @@
insn->operands[0] = dest;
insn->operands[1] = src1;
insn->operands[2] = src2;
+ setupResourceMasks(insn);
dvmCompilerAppendLIR(cUnit, (LIR *) insn);
return insn;
}
-static ArmLIR *newLIR23(CompilationUnit *cUnit, ArmOpCode opCode,
- int srcdest, int src2)
+static ArmLIR *newLIR4(CompilationUnit *cUnit, ArmOpCode opCode,
+ int dest, int src1, int src2, int info)
{
- assert(!isPseudoOpCode(opCode));
- if (EncodingMap[opCode].flags & IS_BINARY_OP)
- return newLIR2(cUnit, opCode, srcdest, src2);
- else
- return newLIR3(cUnit, opCode, srcdest, srcdest, src2);
+ ArmLIR *insn = dvmCompilerNew(sizeof(ArmLIR), true);
+ assert(isPseudoOpCode(opCode) ||
+ (EncodingMap[opCode].flags & IS_QUAD_OP));
+ insn->opCode = opCode;
+ insn->operands[0] = dest;
+ insn->operands[1] = src1;
+ insn->operands[2] = src2;
+ insn->operands[3] = info;
+ setupResourceMasks(insn);
+ dvmCompilerAppendLIR(cUnit, (LIR *) insn);
+ return insn;
}
-/*****************************************************************************/
+/*
+ * If the next instruction is a move-result or move-result-long,
+ * return the target Dalvik instruction and convert the next to a
+ * nop. Otherwise, return -1. Used to optimize method inlining.
+ */
+static int inlinedTarget(MIR *mir)
+{
+ if (mir->next &&
+ ((mir->next->dalvikInsn.opCode == OP_MOVE_RESULT) ||
+ (mir->next->dalvikInsn.opCode == OP_MOVE_RESULT_OBJECT) ||
+ (mir->next->dalvikInsn.opCode == OP_MOVE_RESULT_WIDE))) {
+ mir->next->dalvikInsn.opCode = OP_NOP;
+ return mir->next->dalvikInsn.vA;
+ } else {
+ return -1;
+ }
+}
+
+
/*
* The following are building blocks to insert constants into the pool or
@@ -136,6 +746,17 @@
return NULL;
}
+/*
+ * Generate an ARM_PSEUDO_BARRIER marker to indicate the boundary of special
+ * blocks.
+ */
+static void genBarrier(CompilationUnit *cUnit)
+{
+ ArmLIR *barrier = newLIR0(cUnit, ARM_PSEUDO_BARRIER);
+ /* Mark all resources as being clobbered */
+ barrier->defMask = -1;
+}
+
/* Perform the actual operation for OP_RETURN_* */
static void genReturnCommon(CompilationUnit *cUnit, MIR *mir)
{
@@ -157,34 +778,6 @@
branch->generic.target = (LIR *) pcrLabel;
}
-/*
- * Perform a binary operation on 64-bit operands and leave the results in the
- * r0/r1 pair.
- */
-static void genBinaryOpWide(CompilationUnit *cUnit, int vDest,
- ArmOpCode preinst, ArmOpCode inst,
- int reg0, int reg2)
-{
- int reg1 = NEXT_REG(reg0);
- int reg3 = NEXT_REG(reg2);
- newLIR23(cUnit, preinst, reg0, reg2);
- newLIR23(cUnit, inst, reg1, reg3);
- storeValuePair(cUnit, reg0, reg1, vDest, reg2);
-}
-
-/* Perform a binary operation on 32-bit operands and leave the results in r0. */
-static void genBinaryOp(CompilationUnit *cUnit, int vDest, ArmOpCode inst,
- int reg0, int reg1, int regDest)
-{
- if (EncodingMap[inst].flags & IS_BINARY_OP) {
- newLIR2(cUnit, inst, reg0, reg1);
- storeValue(cUnit, reg0, vDest, reg1);
- } else {
- newLIR3(cUnit, inst, regDest, reg0, reg1);
- storeValue(cUnit, regDest, vDest, reg1);
- }
-}
-
/* Create the PC reconstruction slot if not already done */
static inline ArmLIR *genCheckCommon(CompilationUnit *cUnit, int dOffset,
ArmLIR *branch,
@@ -210,14 +803,16 @@
* Perform a "reg cmp reg" operation and jump to the PCR region if condition
* satisfies.
*/
-static inline ArmLIR *inertRegRegCheck(CompilationUnit *cUnit,
- ArmConditionCode cond,
- int reg1, int reg2, int dOffset,
- ArmLIR *pcrLabel)
+static inline ArmLIR *genRegRegCheck(CompilationUnit *cUnit,
+ ArmConditionCode cond,
+ int reg1, int reg2, int dOffset,
+ ArmLIR *pcrLabel)
{
- newLIR2(cUnit, THUMB_CMP_RR, reg1, reg2);
- ArmLIR *branch = newLIR2(cUnit, THUMB_B_COND, 0, cond);
- return genCheckCommon(cUnit, dOffset, branch, pcrLabel);
+ ArmLIR *res;
+ res = opRegReg(cUnit, OP_CMP, reg1, reg2);
+ ArmLIR *branch = opCondBranch(cUnit, cond);
+ genCheckCommon(cUnit, dOffset, branch, pcrLabel);
+ return res;
}
/*
@@ -250,7 +845,7 @@
static ArmLIR *genBoundsCheck(CompilationUnit *cUnit, int rIndex,
int rBound, int dOffset, ArmLIR *pcrLabel)
{
- return inertRegRegCheck(cUnit, ARM_COND_CS, rIndex, rBound, dOffset,
+ return genRegRegCheck(cUnit, ARM_COND_CS, rIndex, rBound, dOffset,
pcrLabel);
}
@@ -258,7 +853,7 @@
static inline ArmLIR *genTrap(CompilationUnit *cUnit, int dOffset,
ArmLIR *pcrLabel)
{
- ArmLIR *branch = newLIR0(cUnit, THUMB_B_UNCOND);
+ ArmLIR *branch = opNone(cUnit, OP_UNCOND_BR);
return genCheckCommon(cUnit, dOffset, branch, pcrLabel);
}
@@ -277,14 +872,20 @@
/*
* Ping reg0 to the first register of the alternate register pair
*/
- reg0 = (reg2 + 2) & 0x2;
+ reg0 = (reg2 + 2) & 0xa;
reg1 = NEXT_REG(reg0);
loadValue(cUnit, dInsn->vB, reg2);
loadConstant(cUnit, reg3, fieldOffset);
genNullCheck(cUnit, dInsn->vB, reg2, mir->offset, NULL); /* null object? */
- newLIR3(cUnit, THUMB_ADD_RRR, reg2, reg2, reg3);
- newLIR2(cUnit, THUMB_LDMIA, reg2, (1<<reg0 | 1<<reg1));
+ opRegReg(cUnit, OP_ADD, reg2, reg3);
+#if !defined(WITH_SELF_VERIFICATION)
+ loadMultiple(cUnit, reg2, (1<<reg0 | 1<<reg1));
+#else
+ int regMap = reg1 << 8 | reg0 << 4 | reg2;
+ selfVerificationMemOpWrapper(cUnit, regMap,
+ &selfVerificationLoadDoubleword);
+#endif
storeValuePair(cUnit, reg0, reg1, dInsn->vA, reg3);
}
@@ -303,7 +904,7 @@
/*
* Ping reg0 to the first register of the alternate register pair
*/
- reg0 = (reg2 + 2) & 0x2;
+ reg0 = (reg2 + 2) & 0xa;
reg1 = NEXT_REG(reg0);
@@ -312,21 +913,21 @@
updateLiveRegisterPair(cUnit, dInsn->vA, reg0, reg1);
loadConstant(cUnit, reg3, fieldOffset);
genNullCheck(cUnit, dInsn->vB, reg2, mir->offset, NULL); /* null object? */
- newLIR3(cUnit, THUMB_ADD_RRR, reg2, reg2, reg3);
- newLIR2(cUnit, THUMB_STMIA, reg2, (1<<reg0 | 1<<reg1));
+ opRegReg(cUnit, OP_ADD, reg2, reg3);
+#if !defined(WITH_SELF_VERIFICATION)
+ storeMultiple(cUnit, reg2, (1<<reg0 | 1<<reg1));
+#else
+ int regMap = reg1 << 8 | reg0 << 4 | reg2;
+ selfVerificationMemOpWrapper(cUnit, regMap,
+ &selfVerificationStoreDoubleword);
+#endif
}
/*
* Load a field from an object instance
*
- * Inst should be one of:
- * THUMB_LDR_RRR
- * THUMB_LDRB_RRR
- * THUMB_LDRH_RRR
- * THUMB_LDRSB_RRR
- * THUMB_LDRSH_RRR
*/
-static void genIGet(CompilationUnit *cUnit, MIR *mir, ArmOpCode inst,
+static void genIGet(CompilationUnit *cUnit, MIR *mir, OpSize size,
int fieldOffset)
{
DecodedInstruction *dInsn = &mir->dalvikInsn;
@@ -334,23 +935,26 @@
reg0 = selectFirstRegister(cUnit, dInsn->vB, false);
reg1 = NEXT_REG(reg0);
- /* TUNING: write a utility routine to load via base + constant offset */
loadValue(cUnit, dInsn->vB, reg0);
- loadConstant(cUnit, reg1, fieldOffset);
+#if !defined(WITH_SELF_VERIFICATION)
+ loadBaseDisp(cUnit, mir, reg0, fieldOffset, reg1, size, true, dInsn->vB);
+#else
genNullCheck(cUnit, dInsn->vB, reg0, mir->offset, NULL); /* null object? */
- newLIR3(cUnit, inst, reg0, reg0, reg1);
- storeValue(cUnit, reg0, dInsn->vA, reg1);
+ /* Combine address and offset */
+ loadConstant(cUnit, reg1, fieldOffset);
+ opRegReg(cUnit, OP_ADD, reg0, reg1);
+
+ int regMap = reg1 << 4 | reg0;
+ selfVerificationMemOpWrapper(cUnit, regMap, &selfVerificationLoad);
+#endif
+ storeValue(cUnit, reg1, dInsn->vA, reg0);
}
/*
* Store a field to an object instance
*
- * Inst should be one of:
- * THUMB_STR_RRR
- * THUMB_STRB_RRR
- * THUMB_STRH_RRR
*/
-static void genIPut(CompilationUnit *cUnit, MIR *mir, ArmOpCode inst,
+static void genIPut(CompilationUnit *cUnit, MIR *mir, OpSize size,
int fieldOffset)
{
DecodedInstruction *dInsn = &mir->dalvikInsn;
@@ -360,36 +964,38 @@
reg1 = NEXT_REG(reg0);
reg2 = NEXT_REG(reg1);
- /* TUNING: write a utility routine to load via base + constant offset */
loadValue(cUnit, dInsn->vB, reg0);
- loadConstant(cUnit, reg1, fieldOffset);
loadValue(cUnit, dInsn->vA, reg2);
updateLiveRegister(cUnit, dInsn->vA, reg2);
genNullCheck(cUnit, dInsn->vB, reg0, mir->offset, NULL); /* null object? */
- newLIR3(cUnit, inst, reg2, reg0, reg1);
+#if !defined(WITH_SELF_VERIFICATION)
+ storeBaseDisp(cUnit, reg0, fieldOffset, reg2, size, reg1);
+#else
+ /* Combine address and offset */
+ loadConstant(cUnit, reg1, fieldOffset);
+ opRegReg(cUnit, OP_ADD, reg0, reg1);
+
+ int regMap = reg2 << 4 | reg0;
+ selfVerificationMemOpWrapper(cUnit, regMap, &selfVerificationStore);
+
+ opRegReg(cUnit, OP_SUB, reg0, reg1);
+#endif
}
-/* TODO: This should probably be done as an out-of-line instruction handler. */
-
/*
* Generate array load
*
- * Inst should be one of:
- * THUMB_LDR_RRR
- * THUMB_LDRB_RRR
- * THUMB_LDRH_RRR
- * THUMB_LDRSB_RRR
- * THUMB_LDRSH_RRR
*/
-static void genArrayGet(CompilationUnit *cUnit, MIR *mir, ArmOpCode inst,
+static void genArrayGet(CompilationUnit *cUnit, MIR *mir, OpSize size,
int vArray, int vIndex, int vDest, int scale)
{
int lenOffset = offsetof(ArrayObject, length);
int dataOffset = offsetof(ArrayObject, contents);
int reg0, reg1, reg2, reg3;
- reg0 = selectFirstRegister(cUnit, vArray, false);
+ reg0 = selectFirstRegister(cUnit, vArray,
+ (size == LONG) || (size == DOUBLE));
reg1 = NEXT_REG(reg0);
reg2 = NEXT_REG(reg1);
reg3 = NEXT_REG(reg2);
@@ -398,43 +1004,91 @@
loadValue(cUnit, vIndex, reg3);
/* null object? */
- ArmLIR * pcrLabel = genNullCheck(cUnit, vArray, reg2, mir->offset,
- NULL);
- newLIR3(cUnit, THUMB_LDR_RRI5, reg0, reg2, lenOffset >> 2); /* Get len */
- newLIR2(cUnit, THUMB_ADD_RI8, reg2, dataOffset); /* reg2 -> array data */
- genBoundsCheck(cUnit, reg3, reg0, mir->offset, pcrLabel);
- if (scale) {
- newLIR3(cUnit, THUMB_LSL, reg3, reg3, scale);
+ ArmLIR * pcrLabel = NULL;
+
+ if (!(mir->OptimizationFlags & MIR_IGNORE_NULL_CHECK)) {
+ pcrLabel = genNullCheck(cUnit, vArray, reg2, mir->offset, NULL);
}
- if (scale==3) {
- newLIR3(cUnit, inst, reg0, reg2, reg3);
- newLIR2(cUnit, THUMB_ADD_RI8, reg2, 4);
- newLIR3(cUnit, inst, reg1, reg2, reg3);
+
+ if (!(mir->OptimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
+ /* Get len */
+ loadWordDisp(cUnit, reg2, lenOffset, reg0);
+ /* reg2 -> array data */
+ opRegImm(cUnit, OP_ADD, reg2, dataOffset, rNone);
+ genBoundsCheck(cUnit, reg3, reg0, mir->offset, pcrLabel);
+ } else {
+ /* reg2 -> array data */
+ opRegImm(cUnit, OP_ADD, reg2, dataOffset, rNone);
+ }
+#if !defined(WITH_SELF_VERIFICATION)
+ if ((size == LONG) || (size == DOUBLE)) {
+ //TUNING: redo. Make specific wide routine, perhaps use ldmia/fp regs
+ opRegRegImm(cUnit, OP_LSL, reg3, reg3, scale, rNone);
+ loadBaseIndexed(cUnit, reg2, reg3, reg0, 0, WORD);
+ opRegImm(cUnit, OP_ADD, reg2, 4, rNone);
+ loadBaseIndexed(cUnit, reg2, reg3, reg1, 0, WORD);
storeValuePair(cUnit, reg0, reg1, vDest, reg3);
} else {
- newLIR3(cUnit, inst, reg0, reg2, reg3);
+ loadBaseIndexed(cUnit, reg2, reg3, reg0, scale, size);
storeValue(cUnit, reg0, vDest, reg3);
}
-}
+#else
+ //TODO: probably want to move this into loadBaseIndexed
+ void *funct = NULL;
+ switch(size) {
+ case LONG:
+ case DOUBLE:
+ funct = (void*) &selfVerificationLoadDoubleword;
+ break;
+ case WORD:
+ funct = (void*) &selfVerificationLoad;
+ break;
+ case UNSIGNED_HALF:
+ funct = (void*) &selfVerificationLoadHalfword;
+ break;
+ case SIGNED_HALF:
+ funct = (void*) &selfVerificationLoadSignedHalfword;
+ break;
+ case UNSIGNED_BYTE:
+ funct = (void*) &selfVerificationLoadByte;
+ break;
+ case SIGNED_BYTE:
+ funct = (void*) &selfVerificationLoadSignedByte;
+ break;
+ default:
+ assert(0);
+ dvmAbort();
+ }
+ /* Combine address and index */
+ if (scale)
+ opRegRegImm(cUnit, OP_LSL, reg3, reg3, scale, rNone);
+ opRegReg(cUnit, OP_ADD, reg2, reg3);
-/* TODO: This should probably be done as an out-of-line instruction handler. */
+ int regMap = reg1 << 8 | reg0 << 4 | reg2;
+ selfVerificationMemOpWrapper(cUnit, regMap, funct);
+
+ opRegReg(cUnit, OP_SUB, reg2, reg3);
+
+ if ((size == LONG) || (size == DOUBLE))
+ storeValuePair(cUnit, reg0, reg1, vDest, reg3);
+ else
+ storeValue(cUnit, reg0, vDest, reg3);
+#endif
+}
/*
* Generate array store
*
- * Inst should be one of:
- * THUMB_STR_RRR
- * THUMB_STRB_RRR
- * THUMB_STRH_RRR
*/
-static void genArrayPut(CompilationUnit *cUnit, MIR *mir, ArmOpCode inst,
+static void genArrayPut(CompilationUnit *cUnit, MIR *mir, OpSize size,
int vArray, int vIndex, int vSrc, int scale)
{
int lenOffset = offsetof(ArrayObject, length);
int dataOffset = offsetof(ArrayObject, contents);
int reg0, reg1, reg2, reg3;
- reg0 = selectFirstRegister(cUnit, vArray, false);
+ reg0 = selectFirstRegister(cUnit, vArray,
+ (size == LONG) || (size == DOUBLE));
reg1 = NEXT_REG(reg0);
reg2 = NEXT_REG(reg1);
reg3 = NEXT_REG(reg2);
@@ -443,33 +1097,80 @@
loadValue(cUnit, vIndex, reg3);
/* null object? */
- ArmLIR * pcrLabel = genNullCheck(cUnit, vArray, reg2, mir->offset,
- NULL);
- newLIR3(cUnit, THUMB_LDR_RRI5, reg0, reg2, lenOffset >> 2); /* Get len */
- newLIR2(cUnit, THUMB_ADD_RI8, reg2, dataOffset); /* reg2 -> array data */
- genBoundsCheck(cUnit, reg3, reg0, mir->offset, pcrLabel);
+ ArmLIR * pcrLabel = NULL;
+
+ if (!(mir->OptimizationFlags & MIR_IGNORE_NULL_CHECK)) {
+ pcrLabel = genNullCheck(cUnit, vArray, reg2, mir->offset, NULL);
+ }
+
+ if (!(mir->OptimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
+ /* Get len */
+ loadWordDisp(cUnit, reg2, lenOffset, reg0);
+ /* reg2 -> array data */
+ opRegImm(cUnit, OP_ADD, reg2, dataOffset, rNone);
+ genBoundsCheck(cUnit, reg3, reg0, mir->offset, pcrLabel);
+ } else {
+ /* reg2 -> array data */
+ opRegImm(cUnit, OP_ADD, reg2, dataOffset, rNone);
+ }
+
/* at this point, reg2 points to array, reg3 is unscaled index */
- if (scale==3) {
+#if !defined(WITH_SELF_VERIFICATION)
+ if ((size == LONG) || (size == DOUBLE)) {
+ //TUNING: redo. Make specific wide routine, perhaps use ldmia/fp regs
+ loadValuePair(cUnit, vSrc, reg0, reg1);
+ updateLiveRegisterPair(cUnit, vSrc, reg0, reg1);
+ if (scale)
+ opRegRegImm(cUnit, OP_LSL, reg3, reg3, scale, rNone);
+ storeBaseIndexed(cUnit, reg2, reg3, reg0, 0, WORD);
+ opRegImm(cUnit, OP_ADD, reg2, 4, rNone);
+ storeBaseIndexed(cUnit, reg2, reg3, reg1, 0, WORD);
+ } else {
+ loadValue(cUnit, vSrc, reg0);
+ updateLiveRegister(cUnit, vSrc, reg0);
+ storeBaseIndexed(cUnit, reg2, reg3, reg0, scale, size);
+ }
+#else
+ //TODO: probably want to move this into storeBaseIndexed
+ void *funct = NULL;
+ switch(size) {
+ case LONG:
+ case DOUBLE:
+ funct = (void*) &selfVerificationStoreDoubleword;
+ break;
+ case WORD:
+ funct = (void*) &selfVerificationStore;
+ break;
+ case SIGNED_HALF:
+ case UNSIGNED_HALF:
+ funct = (void*) &selfVerificationStoreHalfword;
+ break;
+ case SIGNED_BYTE:
+ case UNSIGNED_BYTE:
+ funct = (void*) &selfVerificationStoreByte;
+ break;
+ default:
+ assert(0);
+ dvmAbort();
+ }
+
+ /* Combine address and index */
+ if ((size == LONG) || (size == DOUBLE)) {
loadValuePair(cUnit, vSrc, reg0, reg1);
updateLiveRegisterPair(cUnit, vSrc, reg0, reg1);
} else {
loadValue(cUnit, vSrc, reg0);
updateLiveRegister(cUnit, vSrc, reg0);
}
- if (scale) {
- newLIR3(cUnit, THUMB_LSL, reg3, reg3, scale);
- }
- /*
- * at this point, reg2 points to array, reg3 is scaled index, and
- * reg0[reg1] is data
- */
- if (scale==3) {
- newLIR3(cUnit, inst, reg0, reg2, reg3);
- newLIR2(cUnit, THUMB_ADD_RI8, reg2, 4);
- newLIR3(cUnit, inst, reg1, reg2, reg3);
- } else {
- newLIR3(cUnit, inst, reg0, reg2, reg3);
- }
+ if (scale)
+ opRegRegImm(cUnit, OP_LSL, reg3, reg3, scale, rNone);
+ opRegReg(cUnit, OP_ADD, reg2, reg3);
+
+ int regMap = reg1 << 8 | reg0 << 4 | reg2;
+ selfVerificationMemOpWrapper(cUnit, regMap, funct);
+
+ opRegReg(cUnit, OP_SUB, reg2, reg3);
+#endif
}
static bool genShiftOpLong(CompilationUnit *cUnit, MIR *mir, int vDest,
@@ -543,8 +1244,7 @@
break;
case OP_NEG_FLOAT: {
loadValue(cUnit, vSrc2, reg0);
- loadConstant(cUnit, reg1, 0x80000000);
- newLIR3(cUnit, THUMB_ADD_RRR, reg0, reg0, reg1);
+ opRegImm(cUnit, OP_ADD, reg0, 0x80000000, reg1);
storeValue(cUnit, reg0, vDest, reg1);
return false;
}
@@ -554,7 +1254,7 @@
loadConstant(cUnit, r2, (int)funct);
loadValue(cUnit, vSrc1, r0);
loadValue(cUnit, vSrc2, r1);
- newLIR1(cUnit, THUMB_BLX_R, r2);
+ opReg(cUnit, OP_BLX, r2);
storeValue(cUnit, r0, vDest, r1);
return false;
}
@@ -599,8 +1299,7 @@
break;
case OP_NEG_DOUBLE: {
loadValuePair(cUnit, vSrc2, reg0, reg1);
- loadConstant(cUnit, reg2, 0x80000000);
- newLIR3(cUnit, THUMB_ADD_RRR, reg1, reg1, reg2);
+ opRegImm(cUnit, OP_ADD, reg1, 0x80000000, reg2);
storeValuePair(cUnit, reg0, reg1, vDest, reg2);
return false;
}
@@ -614,7 +1313,7 @@
loadConstant(cUnit, r4PC, (int)funct);
loadValuePair(cUnit, vSrc1, r0, r1);
loadValuePair(cUnit, vSrc2, r2, r3);
- newLIR1(cUnit, THUMB_BLX_R, r4PC);
+ opReg(cUnit, OP_BLX, r4PC);
storeValuePair(cUnit, r0, r1, vDest, r2);
return false;
}
@@ -622,8 +1321,8 @@
static bool genArithOpLong(CompilationUnit *cUnit, MIR *mir, int vDest,
int vSrc1, int vSrc2)
{
- int firstOp = THUMB_BKPT;
- int secondOp = THUMB_BKPT;
+ OpKind firstOp = OP_BKPT;
+ OpKind secondOp = OP_BKPT;
bool callOut = false;
void *callTgt;
int retReg = r0;
@@ -633,18 +1332,18 @@
switch (mir->dalvikInsn.opCode) {
case OP_NOT_LONG:
- firstOp = THUMB_MVN;
- secondOp = THUMB_MVN;
+ firstOp = OP_MVN;
+ secondOp = OP_MVN;
break;
case OP_ADD_LONG:
case OP_ADD_LONG_2ADDR:
- firstOp = THUMB_ADD_RRR;
- secondOp = THUMB_ADC;
+ firstOp = OP_ADD;
+ secondOp = OP_ADC;
break;
case OP_SUB_LONG:
case OP_SUB_LONG_2ADDR:
- firstOp = THUMB_SUB_RRR;
- secondOp = THUMB_SBC;
+ firstOp = OP_SUB;
+ secondOp = OP_SBC;
break;
case OP_MUL_LONG:
case OP_MUL_LONG_2ADDR:
@@ -669,18 +1368,18 @@
break;
case OP_AND_LONG:
case OP_AND_LONG_2ADDR:
- firstOp = THUMB_AND_RR;
- secondOp = THUMB_AND_RR;
+ firstOp = OP_AND;
+ secondOp = OP_AND;
break;
case OP_OR_LONG:
case OP_OR_LONG_2ADDR:
- firstOp = THUMB_ORR;
- secondOp = THUMB_ORR;
+ firstOp = OP_OR;
+ secondOp = OP_OR;
break;
case OP_XOR_LONG:
case OP_XOR_LONG_2ADDR:
- firstOp = THUMB_EOR;
- secondOp = THUMB_EOR;
+ firstOp = OP_XOR;
+ secondOp = OP_XOR;
break;
case OP_NEG_LONG: {
reg0 = selectFirstRegister(cUnit, vSrc2, true);
@@ -690,8 +1389,8 @@
loadValuePair(cUnit, vSrc2, reg0, reg1);
loadConstant(cUnit, reg3, 0);
- newLIR3(cUnit, THUMB_SUB_RRR, reg2, reg3, reg0);
- newLIR2(cUnit, THUMB_SBC, reg3, reg1);
+ opRegRegReg(cUnit, OP_SUB, reg2, reg3, reg0);
+ opRegReg(cUnit, OP_SBC, reg3, reg1);
storeValuePair(cUnit, reg2, reg3, vDest, reg0);
return false;
}
@@ -707,16 +1406,18 @@
loadValuePair(cUnit, vSrc1, reg0, reg1);
loadValuePair(cUnit, vSrc2, reg2, reg3);
- genBinaryOpWide(cUnit, vDest, firstOp, secondOp, reg0, reg2);
+ opRegReg(cUnit, firstOp, reg0, reg2);
+ opRegReg(cUnit, secondOp, reg1, reg3);
+ storeValuePair(cUnit, reg0, reg1, vDest, reg2);
/*
- * Don't optimize the regsiter usage here as they are governed by the EABI
+ * Don't optimize the register usage here as they are governed by the EABI
* calling convention.
*/
} else {
loadValuePair(cUnit, vSrc2, r2, r3);
loadConstant(cUnit, r4PC, (int) callTgt);
loadValuePair(cUnit, vSrc1, r0, r1);
- newLIR1(cUnit, THUMB_BLX_R, r4PC);
+ opReg(cUnit, OP_BLX, r4PC);
storeValuePair(cUnit, retReg, retReg+1, vDest, r4PC);
}
return false;
@@ -725,9 +1426,10 @@
static bool genArithOpInt(CompilationUnit *cUnit, MIR *mir, int vDest,
int vSrc1, int vSrc2)
{
- int armOp = THUMB_BKPT;
+ OpKind op = OP_BKPT;
bool callOut = false;
bool checkZero = false;
+ bool threeOperand = false;
int retReg = r0;
void *callTgt;
int reg0, reg1, regDest;
@@ -738,22 +1440,24 @@
switch (mir->dalvikInsn.opCode) {
case OP_NEG_INT:
- armOp = THUMB_NEG;
+ op = OP_NEG;
break;
case OP_NOT_INT:
- armOp = THUMB_MVN;
+ op = OP_MVN;
break;
case OP_ADD_INT:
case OP_ADD_INT_2ADDR:
- armOp = THUMB_ADD_RRR;
+ op = OP_ADD;
+ threeOperand = true;
break;
case OP_SUB_INT:
case OP_SUB_INT_2ADDR:
- armOp = THUMB_SUB_RRR;
+ op = OP_SUB;
+ threeOperand = true;
break;
case OP_MUL_INT:
case OP_MUL_INT_2ADDR:
- armOp = THUMB_MUL;
+ op = OP_MUL;
break;
case OP_DIV_INT:
case OP_DIV_INT_2ADDR:
@@ -772,27 +1476,27 @@
break;
case OP_AND_INT:
case OP_AND_INT_2ADDR:
- armOp = THUMB_AND_RR;
+ op = OP_AND;
break;
case OP_OR_INT:
case OP_OR_INT_2ADDR:
- armOp = THUMB_ORR;
+ op = OP_OR;
break;
case OP_XOR_INT:
case OP_XOR_INT_2ADDR:
- armOp = THUMB_EOR;
+ op = OP_XOR;
break;
case OP_SHL_INT:
case OP_SHL_INT_2ADDR:
- armOp = THUMB_LSLV;
+ op = OP_LSL;
break;
case OP_SHR_INT:
case OP_SHR_INT_2ADDR:
- armOp = THUMB_ASRV;
+ op = OP_ASR;
break;
case OP_USHR_INT:
case OP_USHR_INT_2ADDR:
- armOp = THUMB_LSRV;
+ op = OP_LSR;
break;
default:
LOGE("Invalid word arith op: 0x%x(%d)",
@@ -808,7 +1512,13 @@
loadValue(cUnit, vSrc1, reg0); /* Should be optimized away */
loadValue(cUnit, vSrc2, reg1);
- genBinaryOp(cUnit, vDest, armOp, reg0, reg1, regDest);
+ if (threeOperand) {
+ opRegRegReg(cUnit, op, regDest, reg0, reg1);
+ storeValue(cUnit, regDest, vDest, reg1);
+ } else {
+ opRegReg(cUnit, op, reg0, reg1);
+ storeValue(cUnit, reg0, vDest, reg1);
+ }
} else {
reg0 = selectFirstRegister(cUnit, vSrc2, false);
reg1 = NEXT_REG(reg0);
@@ -816,7 +1526,13 @@
loadValue(cUnit, vSrc1, reg1); /* Load this value first */
loadValue(cUnit, vSrc2, reg0); /* May be optimized away */
- genBinaryOp(cUnit, vDest, armOp, reg1, reg0, regDest);
+ if (threeOperand) {
+ opRegRegReg(cUnit, op, regDest, reg1, reg0);
+ storeValue(cUnit, regDest, vDest, reg1);
+ } else {
+ opRegReg(cUnit, op, reg1, reg0);
+ storeValue(cUnit, reg1, vDest, reg0);
+ }
}
} else {
/*
@@ -841,7 +1557,7 @@
if (checkZero) {
genNullCheck(cUnit, vSrc2, r1, mir->offset, NULL);
}
- newLIR1(cUnit, THUMB_BLX_R, r2);
+ opReg(cUnit, OP_BLX, r2);
storeValue(cUnit, retReg, vDest, r2);
}
return false;
@@ -900,7 +1616,7 @@
} else {
loadValuePair(cUnit, mir->dalvikInsn.vB, r0, r1);
}
- newLIR1(cUnit, THUMB_BLX_R, r2);
+ opReg(cUnit, OP_BLX, r2);
if (tgtSize == 1) {
storeValue(cUnit, r0, mir->dalvikInsn.vA, r1);
} else {
@@ -909,136 +1625,6 @@
return false;
}
-static bool genInlinedStringLength(CompilationUnit *cUnit, MIR *mir)
-{
- DecodedInstruction *dInsn = &mir->dalvikInsn;
- int offset = offsetof(InterpState, retval);
- int regObj = selectFirstRegister(cUnit, dInsn->arg[0], false);
- int reg1 = NEXT_REG(regObj);
- loadValue(cUnit, dInsn->arg[0], regObj);
- genNullCheck(cUnit, dInsn->arg[0], regObj, mir->offset, NULL);
- loadWordDisp(cUnit, regObj, gDvm.offJavaLangString_count, reg1);
- newLIR3(cUnit, THUMB_STR_RRI5, reg1, rGLUE, offset >> 2);
- return false;
-}
-
-/*
- * NOTE: The amount of code for this body suggests it ought to
- * be handled in a template (and could also be coded quite a bit
- * more efficiently in ARM). However, the code is dependent on the
- * internal structure layout of string objects which are most safely
- * known at run time.
- * TUNING: One possibility (which could also be used for StringCompareTo
- * and StringEquals) is to generate string access helper subroutines on
- * Jit startup, and then call them from the translated inline-executes.
- */
-static bool genInlinedStringCharAt(CompilationUnit *cUnit, MIR *mir)
-{
- DecodedInstruction *dInsn = &mir->dalvikInsn;
- int offset = offsetof(InterpState, retval);
- int contents = offsetof(ArrayObject, contents);
- int regObj = selectFirstRegister(cUnit, dInsn->arg[0], false);
- int regIdx = NEXT_REG(regObj);
- int regMax = NEXT_REG(regIdx);
- int regOff = NEXT_REG(regMax);
- loadValue(cUnit, dInsn->arg[0], regObj);
- loadValue(cUnit, dInsn->arg[1], regIdx);
- ArmLIR * pcrLabel = genNullCheck(cUnit, dInsn->arg[0], regObj,
- mir->offset, NULL);
- loadWordDisp(cUnit, regObj, gDvm.offJavaLangString_count, regMax);
- loadWordDisp(cUnit, regObj, gDvm.offJavaLangString_offset, regOff);
- loadWordDisp(cUnit, regObj, gDvm.offJavaLangString_value, regObj);
- genBoundsCheck(cUnit, regIdx, regMax, mir->offset, pcrLabel);
-
- newLIR2(cUnit, THUMB_ADD_RI8, regObj, contents);
- newLIR3(cUnit, THUMB_ADD_RRR, regIdx, regIdx, regOff);
- newLIR3(cUnit, THUMB_ADD_RRR, regIdx, regIdx, regIdx);
- newLIR3(cUnit, THUMB_LDRH_RRR, regMax, regObj, regIdx);
- newLIR3(cUnit, THUMB_STR_RRI5, regMax, rGLUE, offset >> 2);
- return false;
-}
-
-static bool genInlinedAbsInt(CompilationUnit *cUnit, MIR *mir)
-{
- int offset = offsetof(InterpState, retval);
- DecodedInstruction *dInsn = &mir->dalvikInsn;
- int reg0 = selectFirstRegister(cUnit, dInsn->arg[0], false);
- int sign = NEXT_REG(reg0);
- /* abs(x) = y<=x>>31, (x+y)^y. Shorter in ARM/THUMB2, no skip in THUMB */
- loadValue(cUnit, dInsn->arg[0], reg0);
- newLIR3(cUnit, THUMB_ASR, sign, reg0, 31);
- newLIR3(cUnit, THUMB_ADD_RRR, reg0, reg0, sign);
- newLIR2(cUnit, THUMB_EOR, reg0, sign);
- newLIR3(cUnit, THUMB_STR_RRI5, reg0, rGLUE, offset >> 2);
- return false;
-}
-
-static bool genInlinedAbsFloat(CompilationUnit *cUnit, MIR *mir)
-{
- int offset = offsetof(InterpState, retval);
- DecodedInstruction *dInsn = &mir->dalvikInsn;
- int reg0 = selectFirstRegister(cUnit, dInsn->arg[0], false);
- int signMask = NEXT_REG(reg0);
- loadValue(cUnit, dInsn->arg[0], reg0);
- loadConstant(cUnit, signMask, 0x7fffffff);
- newLIR2(cUnit, THUMB_AND_RR, reg0, signMask);
- newLIR3(cUnit, THUMB_STR_RRI5, reg0, rGLUE, offset >> 2);
- return false;
-}
-
-static bool genInlinedAbsDouble(CompilationUnit *cUnit, MIR *mir)
-{
- int offset = offsetof(InterpState, retval);
- DecodedInstruction *dInsn = &mir->dalvikInsn;
- int oplo = selectFirstRegister(cUnit, dInsn->arg[0], true);
- int ophi = NEXT_REG(oplo);
- int signMask = NEXT_REG(ophi);
- loadValuePair(cUnit, dInsn->arg[0], oplo, ophi);
- loadConstant(cUnit, signMask, 0x7fffffff);
- newLIR3(cUnit, THUMB_STR_RRI5, oplo, rGLUE, offset >> 2);
- newLIR2(cUnit, THUMB_AND_RR, ophi, signMask);
- newLIR3(cUnit, THUMB_STR_RRI5, ophi, rGLUE, (offset >> 2)+1);
- return false;
-}
-
- /* No select in thumb, so we need to branch. Thumb2 will do better */
-static bool genInlinedMinMaxInt(CompilationUnit *cUnit, MIR *mir, bool isMin)
-{
- int offset = offsetof(InterpState, retval);
- DecodedInstruction *dInsn = &mir->dalvikInsn;
- int reg0 = selectFirstRegister(cUnit, dInsn->arg[0], false);
- int reg1 = NEXT_REG(reg0);
- loadValue(cUnit, dInsn->arg[0], reg0);
- loadValue(cUnit, dInsn->arg[1], reg1);
- newLIR2(cUnit, THUMB_CMP_RR, reg0, reg1);
- ArmLIR *branch1 = newLIR2(cUnit, THUMB_B_COND, 2,
- isMin ? ARM_COND_LT : ARM_COND_GT);
- newLIR2(cUnit, THUMB_MOV_RR, reg0, reg1);
- ArmLIR *target =
- newLIR3(cUnit, THUMB_STR_RRI5, reg0, rGLUE, offset >> 2);
- branch1->generic.target = (LIR *)target;
- return false;
-}
-
-static bool genInlinedAbsLong(CompilationUnit *cUnit, MIR *mir)
-{
- int offset = offsetof(InterpState, retval);
- DecodedInstruction *dInsn = &mir->dalvikInsn;
- int oplo = selectFirstRegister(cUnit, dInsn->arg[0], true);
- int ophi = NEXT_REG(oplo);
- int sign = NEXT_REG(ophi);
- /* abs(x) = y<=x>>31, (x+y)^y. Shorter in ARM/THUMB2, no skip in THUMB */
- loadValuePair(cUnit, dInsn->arg[0], oplo, ophi);
- newLIR3(cUnit, THUMB_ASR, sign, ophi, 31);
- newLIR3(cUnit, THUMB_ADD_RRR, oplo, oplo, sign);
- newLIR2(cUnit, THUMB_ADC, ophi, sign);
- newLIR2(cUnit, THUMB_EOR, oplo, sign);
- newLIR2(cUnit, THUMB_EOR, ophi, sign);
- newLIR3(cUnit, THUMB_STR_RRI5, oplo, rGLUE, offset >> 2);
- newLIR3(cUnit, THUMB_STR_RRI5, ophi, rGLUE, (offset >> 2)+1);
- return false;
-}
-
static void genProcessArgsNoRange(CompilationUnit *cUnit, MIR *mir,
DecodedInstruction *dInsn,
ArmLIR **pcrLabel)
@@ -1053,15 +1639,14 @@
}
if (regMask) {
/* Up to 5 args are pushed on top of FP - sizeofStackSaveArea */
- newLIR2(cUnit, THUMB_MOV_RR, r7, rFP);
- newLIR2(cUnit, THUMB_SUB_RI8, r7,
- sizeof(StackSaveArea) + (dInsn->vA << 2));
+ opRegRegImm(cUnit, OP_SUB, r7, rFP,
+ sizeof(StackSaveArea) + (dInsn->vA << 2), rNone);
/* generate null check */
if (pcrLabel) {
*pcrLabel = genNullCheck(cUnit, dInsn->arg[0], r0, mir->offset,
NULL);
}
- newLIR2(cUnit, THUMB_STMIA, r7, regMask);
+ storeMultiple(cUnit, r7, regMask);
}
}
@@ -1076,25 +1661,19 @@
* r4PC : &rFP[vC]
* r7: &newFP[0]
*/
- if (srcOffset < 8) {
- newLIR3(cUnit, THUMB_ADD_RRI3, r4PC, rFP, srcOffset);
- } else {
- loadConstant(cUnit, r4PC, srcOffset);
- newLIR3(cUnit, THUMB_ADD_RRR, r4PC, rFP, r4PC);
- }
+ opRegRegImm(cUnit, OP_ADD, r4PC, rFP, srcOffset, rNone);
/* load [r0 .. min(numArgs,4)] */
regMask = (1 << ((numArgs < 4) ? numArgs : 4)) - 1;
- newLIR2(cUnit, THUMB_LDMIA, r4PC, regMask);
+ /*
+ * Protect the loadMultiple instruction from being reordered with other
+ * Dalvik stack accesses.
+ */
+ genBarrier(cUnit);
+ loadMultiple(cUnit, r4PC, regMask);
+ genBarrier(cUnit);
- if (sizeof(StackSaveArea) + (numArgs << 2) < 256) {
- newLIR2(cUnit, THUMB_MOV_RR, r7, rFP);
- newLIR2(cUnit, THUMB_SUB_RI8, r7,
- sizeof(StackSaveArea) + (numArgs << 2));
- } else {
- loadConstant(cUnit, r7, sizeof(StackSaveArea) + (numArgs << 2));
- newLIR3(cUnit, THUMB_SUB_RRR, r7, rFP, r7);
- }
-
+ opRegRegImm(cUnit, OP_SUB, r7, rFP,
+ sizeof(StackSaveArea) + (numArgs << 2), rNone);
/* generate null check */
if (pcrLabel) {
*pcrLabel = genNullCheck(cUnit, dInsn->vC, r0, mir->offset, NULL);
@@ -1108,37 +1687,50 @@
ArmLIR *loopLabel = NULL;
/*
* r0 contains "this" and it will be used later, so push it to the stack
- * first. Pushing r5 is just for stack alignment purposes.
+ * first. Pushing r5 (rFP) is just for stack alignment purposes.
*/
- newLIR1(cUnit, THUMB_PUSH, 1 << r0 | 1 << 5);
+ opImm(cUnit, OP_PUSH, (1 << r0 | 1 << rFP));
/* No need to generate the loop structure if numArgs <= 11 */
if (numArgs > 11) {
loadConstant(cUnit, 5, ((numArgs - 4) >> 2) << 2);
loopLabel = newLIR0(cUnit, ARM_PSEUDO_TARGET_LABEL);
+ loopLabel->defMask = ENCODE_ALL;
}
- newLIR2(cUnit, THUMB_STMIA, r7, regMask);
- newLIR2(cUnit, THUMB_LDMIA, r4PC, regMask);
+ storeMultiple(cUnit, r7, regMask);
+ /*
+ * Protect the loadMultiple instruction from being reordered with other
+ * Dalvik stack accesses.
+ */
+ genBarrier(cUnit);
+ loadMultiple(cUnit, r4PC, regMask);
+ genBarrier(cUnit);
/* No need to generate the loop structure if numArgs <= 11 */
if (numArgs > 11) {
- newLIR2(cUnit, THUMB_SUB_RI8, 5, 4);
+ opRegImm(cUnit, OP_SUB, rFP, 4, rNone);
genConditionalBranch(cUnit, ARM_COND_NE, loopLabel);
}
}
/* Save the last batch of loaded values */
- newLIR2(cUnit, THUMB_STMIA, r7, regMask);
+ storeMultiple(cUnit, r7, regMask);
/* Generate the loop epilogue - don't use r0 */
if ((numArgs > 4) && (numArgs % 4)) {
regMask = ((1 << (numArgs & 0x3)) - 1) << 1;
- newLIR2(cUnit, THUMB_LDMIA, r4PC, regMask);
+ /*
+ * Protect the loadMultiple instruction from being reordered with other
+ * Dalvik stack accesses.
+ */
+ genBarrier(cUnit);
+ loadMultiple(cUnit, r4PC, regMask);
+ genBarrier(cUnit);
}
if (numArgs >= 8)
- newLIR1(cUnit, THUMB_POP, 1 << r0 | 1 << 5);
+ opImm(cUnit, OP_POP, (1 << r0 | 1 << rFP));
/* Save the modulo 4 arguments */
if ((numArgs > 4) && (numArgs % 4)) {
- newLIR2(cUnit, THUMB_STMIA, r7, regMask);
+ storeMultiple(cUnit, r7, regMask);
}
}
@@ -1154,8 +1746,7 @@
ArmLIR *retChainingCell = &labelList[bb->fallThrough->id];
/* r1 = &retChainingCell */
- ArmLIR *addrRetChain = newLIR3(cUnit, THUMB_ADD_PC_REL,
- r1, 0, 0);
+ ArmLIR *addrRetChain = opRegRegImm(cUnit, OP_ADD, r1, rpc, 0, rNone);
/* r4PC = dalvikCallsite */
loadConstant(cUnit, r4PC,
(int) (cUnit->method->insns + mir->offset));
@@ -1215,13 +1806,12 @@
(int) (cUnit->method->insns + mir->offset));
/* r1 = &retChainingCell */
- ArmLIR *addrRetChain = newLIR2(cUnit, THUMB_ADD_PC_REL,
- r1, 0);
+ ArmLIR *addrRetChain = opRegRegImm(cUnit, OP_ADD, r1, rpc, 0, rNone);
addrRetChain->generic.target = (LIR *) retChainingCell;
/* r2 = &predictedChainingCell */
- ArmLIR *predictedChainingCell =
- newLIR2(cUnit, THUMB_ADD_PC_REL, r2, 0);
+ ArmLIR *predictedChainingCell = opRegRegImm(cUnit, OP_ADD, r2, rpc, 0,
+ rNone);
predictedChainingCell->generic.target = (LIR *) predChainingCell;
genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN);
@@ -1256,23 +1846,15 @@
*/
/* r0 <- calleeMethod */
- if (methodIndex < 32) {
- newLIR3(cUnit, THUMB_LDR_RRI5, r0, r7, methodIndex);
- } else {
- loadConstant(cUnit, r0, methodIndex<<2);
- newLIR3(cUnit, THUMB_LDR_RRR, r0, r7, r0);
- }
+ loadWordDisp(cUnit, r7, methodIndex * 4, r0);
/* Check if rechain limit is reached */
- newLIR2(cUnit, THUMB_CMP_RI8, r1, 0);
+ opRegImm(cUnit, OP_CMP, r1, 0, rNone);
- ArmLIR *bypassRechaining =
- newLIR2(cUnit, THUMB_B_COND, 0, ARM_COND_GT);
+ ArmLIR *bypassRechaining = opCondBranch(cUnit, ARM_COND_GT);
- newLIR3(cUnit, THUMB_LDR_RRI5, r7, rGLUE,
- offsetof(InterpState,
- jitToInterpEntries.dvmJitToPatchPredictedChain)
- >> 2);
+ loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
+ jitToInterpEntries.dvmJitToPatchPredictedChain), r7);
/*
* r0 = calleeMethod
@@ -1283,10 +1865,10 @@
* when patching the chaining cell and will be clobbered upon
* returning so it will be reconstructed again.
*/
- newLIR1(cUnit, THUMB_BLX_R, r7);
+ opReg(cUnit, OP_BLX, r7);
/* r1 = &retChainingCell */
- addrRetChain = newLIR3(cUnit, THUMB_ADD_PC_REL, r1, 0, 0);
+ addrRetChain = opRegRegImm(cUnit, OP_ADD, r1, rpc, 0, rNone);
addrRetChain->generic.target = (LIR *) retChainingCell;
bypassRechaining->generic.target = (LIR *) addrRetChain;
@@ -1318,16 +1900,14 @@
MIR *mir)
{
/* r3 now contains this->clazz */
- newLIR3(cUnit, THUMB_LDR_RRI5, r3, r0,
- offsetof(Object, clazz) >> 2);
+ loadWordDisp(cUnit, r0, offsetof(Object, clazz), r3);
/*
* r2 now contains predicted class. The starting offset of the
* cached value is 4 bytes into the chaining cell.
*/
ArmLIR *getPredictedClass =
- newLIR3(cUnit, THUMB_LDR_PC_REL, r2, 0,
- offsetof(PredictedChainingCell, clazz));
+ loadWordDisp(cUnit, rpc, offsetof(PredictedChainingCell, clazz), r2);
getPredictedClass->generic.target = (LIR *) predChainingCell;
/*
@@ -1335,14 +1915,12 @@
* cached value is 8 bytes into the chaining cell.
*/
ArmLIR *getPredictedMethod =
- newLIR3(cUnit, THUMB_LDR_PC_REL, r0, 0,
- offsetof(PredictedChainingCell, method));
+ loadWordDisp(cUnit, rpc, offsetof(PredictedChainingCell, method), r0);
getPredictedMethod->generic.target = (LIR *) predChainingCell;
/* Load the stats counter to see if it is time to unchain and refresh */
ArmLIR *getRechainingRequestCount =
- newLIR3(cUnit, THUMB_LDR_PC_REL, r7, 0,
- offsetof(PredictedChainingCell, counter));
+ loadWordDisp(cUnit, rpc, offsetof(PredictedChainingCell, counter), r7);
getRechainingRequestCount->generic.target =
(LIR *) predChainingCell;
@@ -1351,14 +1929,13 @@
(int) (cUnit->method->insns + mir->offset));
/* r1 = &retChainingCell */
- ArmLIR *addrRetChain = newLIR3(cUnit, THUMB_ADD_PC_REL,
- r1, 0, 0);
+ ArmLIR *addrRetChain = opRegRegImm(cUnit, OP_ADD, r1, rpc, 0, rNone);
addrRetChain->generic.target = (LIR *) retChainingCell;
/* Check if r2 (predicted class) == r3 (actual class) */
- newLIR2(cUnit, THUMB_CMP_RR, r2, r3);
+ opRegReg(cUnit, OP_CMP, r2, r3);
- return newLIR2(cUnit, THUMB_B_COND, 0, ARM_COND_EQ);
+ return opCondBranch(cUnit, ARM_COND_EQ);
}
/* Geneate a branch to go back to the interpreter */
@@ -1366,9 +1943,10 @@
{
/* r0 = dalvik pc */
loadConstant(cUnit, r0, (int) (cUnit->method->insns + offset));
- newLIR3(cUnit, THUMB_LDR_RRI5, r1, rGLUE,
- offsetof(InterpState, jitToInterpEntries.dvmJitToInterpPunt) >> 2);
- newLIR1(cUnit, THUMB_BLX_R, r1);
+ loadWordDisp(cUnit, r0, offsetof(Object, clazz), r3);
+ loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
+ jitToInterpEntries.dvmJitToInterpPunt), r1);
+ opReg(cUnit, OP_BLX, r1);
}
/*
@@ -1386,16 +1964,129 @@
}
int entryAddr = offsetof(InterpState,
jitToInterpEntries.dvmJitToInterpSingleStep);
- newLIR3(cUnit, THUMB_LDR_RRI5, r2, rGLUE, entryAddr >> 2);
+ loadWordDisp(cUnit, rGLUE, entryAddr, r2);
/* r0 = dalvik pc */
loadConstant(cUnit, r0, (int) (cUnit->method->insns + mir->offset));
/* r1 = dalvik pc of following instruction */
loadConstant(cUnit, r1, (int) (cUnit->method->insns + mir->next->offset));
- newLIR1(cUnit, THUMB_BLX_R, r2);
+ opReg(cUnit, OP_BLX, r2);
}
+/* Generate conditional branch instructions */
+static ArmLIR *genConditionalBranch(CompilationUnit *cUnit,
+ ArmConditionCode cond,
+ ArmLIR *target)
+{
+ ArmLIR *branch = opCondBranch(cUnit, cond);
+ branch->generic.target = (LIR *) target;
+ return branch;
+}
-/*****************************************************************************/
+/* Generate unconditional branch instructions */
+static ArmLIR *genUnconditionalBranch(CompilationUnit *cUnit, ArmLIR *target)
+{
+ ArmLIR *branch = opNone(cUnit, OP_UNCOND_BR);
+ branch->generic.target = (LIR *) target;
+ return branch;
+}
+
+/* Load the address of a Dalvik register on the frame */
+static ArmLIR *loadValueAddress(CompilationUnit *cUnit, int vSrc, int rDest)
+{
+ return opRegRegImm(cUnit, OP_ADD, rDest, rFP, vSrc*4, rNone);
+}
+
+/* Load a single value from rFP[src] and store them into rDest */
+static ArmLIR *loadValue(CompilationUnit *cUnit, int vSrc, int rDest)
+{
+ return loadBaseDisp(cUnit, NULL, rFP, vSrc * 4, rDest, WORD, false, -1);
+}
+
+/* Load a word at base + displacement. Displacement must be word multiple */
+static ArmLIR *loadWordDisp(CompilationUnit *cUnit, int rBase, int displacement,
+ int rDest)
+{
+ return loadBaseDisp(cUnit, NULL, rBase, displacement, rDest, WORD, false,
+ -1);
+}
+
+static ArmLIR *storeWordDisp(CompilationUnit *cUnit, int rBase,
+ int displacement, int rSrc, int rScratch)
+{
+ return storeBaseDisp(cUnit, rBase, displacement, rSrc, WORD, rScratch);
+}
+
+/* Store a value from rSrc to vDest */
+static ArmLIR *storeValue(CompilationUnit *cUnit, int rSrc, int vDest,
+ int rScratch)
+{
+ killNullCheckedRegister(cUnit, vDest);
+ updateLiveRegister(cUnit, vDest, rSrc);
+ return storeBaseDisp(cUnit, rFP, vDest * 4, rSrc, WORD, rScratch);
+}
+/*
+ * Load a pair of values of rFP[src..src+1] and store them into rDestLo and
+ * rDestHi
+ */
+static ArmLIR *loadValuePair(CompilationUnit *cUnit, int vSrc, int rDestLo,
+ int rDestHi)
+{
+ ArmLIR *res;
+ /* Use reg + imm5*4 to load the values if possible */
+ if (vSrc <= 30) {
+ res = loadWordDisp(cUnit, rFP, vSrc*4, rDestLo);
+ loadWordDisp(cUnit, rFP, (vSrc+1)*4, rDestHi);
+ } else {
+ assert(rDestLo < rDestHi);
+ res = loadValueAddress(cUnit, vSrc, rDestLo);
+ /*
+ * Protect the loadMultiple instruction from being reordered with other
+ * Dalvik stack accesses.
+ */
+ genBarrier(cUnit);
+ loadMultiple(cUnit, rDestLo, (1<<rDestLo) | (1<<rDestHi));
+ genBarrier(cUnit);
+ }
+ return res;
+}
+
+/*
+ * Store a pair of values of rSrc and rSrc+1 and store them into vDest and
+ * vDest+1
+ */
+static ArmLIR *storeValuePair(CompilationUnit *cUnit, int rSrcLo, int rSrcHi,
+ int vDest, int rScratch)
+{
+ ArmLIR *res;
+ killNullCheckedRegister(cUnit, vDest);
+ killNullCheckedRegister(cUnit, vDest+1);
+ updateLiveRegisterPair(cUnit, vDest, rSrcLo, rSrcHi);
+
+ /* Use reg + imm5*4 to store the values if possible */
+ if (vDest <= 30) {
+ res = storeWordDisp(cUnit, rFP, vDest*4, rSrcLo, rScratch);
+ storeWordDisp(cUnit, rFP, (vDest+1)*4, rSrcHi, rScratch);
+ } else {
+ assert(rSrcLo < rSrcHi);
+ res = loadValueAddress(cUnit, vDest, rScratch);
+ /*
+ * Protect the storeMultiple instruction from being reordered with
+ * other Dalvik stack accesses.
+ */
+ genBarrier(cUnit);
+ storeMultiple(cUnit, rScratch, (1<<rSrcLo) | (1 << rSrcHi));
+ genBarrier(cUnit);
+ }
+ return res;
+}
+
+static ArmLIR *genRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
+{
+ ArmLIR *res = dvmCompilerRegCopy(cUnit, rDest, rSrc);
+ dvmCompilerAppendLIR(cUnit, (LIR*)res);
+ return res;
+}
+
/*
* The following are the first-level codegen routines that analyze the format
* of each bytecode then either dispatch special purpose codegen routines
@@ -1455,7 +2146,7 @@
reg1 = NEXT_REG(reg0);
reg2 = NEXT_REG(reg1);
loadConstant(cUnit, reg0, mir->dalvikInsn.vB);
- newLIR3(cUnit, THUMB_ASR, reg1, reg0, 31);
+ opRegRegImm(cUnit, OP_ASR, reg1, reg0, 31, rNone);
storeValuePair(cUnit, reg0, reg1, mir->dalvikInsn.vA, reg2);
break;
}
@@ -1512,10 +2203,6 @@
int regvNoneWide = selectFirstRegister(cUnit, vNone, true);
switch (mir->dalvikInsn.opCode) {
- /*
- * TODO: Verify that we can ignore the resolution check here because
- * it will have already successfully been interpreted once
- */
case OP_CONST_STRING_JUMBO:
case OP_CONST_STRING: {
void *strPtr = (void*)
@@ -1525,10 +2212,6 @@
storeValue(cUnit, regvNone, mir->dalvikInsn.vA, NEXT_REG(regvNone));
break;
}
- /*
- * TODO: Verify that we can ignore the resolution check here because
- * it will have already successfully been interpreted once
- */
case OP_CONST_CLASS: {
void *classPtr = (void*)
(cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
@@ -1548,7 +2231,13 @@
(cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
assert(fieldPtr != NULL);
loadConstant(cUnit, regvNone, (int) fieldPtr + valOffset);
- newLIR3(cUnit, THUMB_LDR_RRI5, regvNone, regvNone, 0);
+#if !defined(WITH_SELF_VERIFICATION)
+ loadWordDisp(cUnit, regvNone, 0, regvNone);
+#else
+ int regMap = regvNone << 4 | regvNone;
+ selfVerificationMemOpWrapper(cUnit, regMap, &selfVerificationLoad);
+
+#endif
storeValue(cUnit, regvNone, mir->dalvikInsn.vA, NEXT_REG(regvNone));
break;
}
@@ -1563,7 +2252,14 @@
reg1 = NEXT_REG(reg0);
reg2 = NEXT_REG(reg1);
loadConstant(cUnit, reg2, (int) fieldPtr + valOffset);
- newLIR2(cUnit, THUMB_LDMIA, reg2, (1<<reg0 | 1<<reg1));
+#if !defined(WITH_SELF_VERIFICATION)
+ loadMultiple(cUnit, reg2, (1<<reg0 | 1<<reg1));
+#else
+ int regMap = reg1 << 8 | reg0 << 4 | reg2;
+ selfVerificationMemOpWrapper(cUnit, regMap,
+ &selfVerificationLoadDoubleword);
+
+#endif
storeValuePair(cUnit, reg0, reg1, mir->dalvikInsn.vA, reg2);
break;
}
@@ -1581,7 +2277,12 @@
loadValue(cUnit, mir->dalvikInsn.vA, regvA);
updateLiveRegister(cUnit, mir->dalvikInsn.vA, regvA);
loadConstant(cUnit, NEXT_REG(regvA), (int) fieldPtr + valOffset);
- newLIR3(cUnit, THUMB_STR_RRI5, regvA, NEXT_REG(regvA), 0);
+#if !defined(WITH_SELF_VERIFICATION)
+ storeWordDisp(cUnit, NEXT_REG(regvA), 0 , regvA, -1);
+#else
+ int regMap = regvA << 4 | NEXT_REG(regvA);
+ selfVerificationMemOpWrapper(cUnit, regMap, &selfVerificationStore);
+#endif
break;
}
case OP_SPUT_WIDE: {
@@ -1597,7 +2298,13 @@
loadValuePair(cUnit, mir->dalvikInsn.vA, reg0, reg1);
updateLiveRegisterPair(cUnit, mir->dalvikInsn.vA, reg0, reg1);
loadConstant(cUnit, reg2, (int) fieldPtr + valOffset);
- newLIR2(cUnit, THUMB_STMIA, reg2, (1<<reg0 | 1<<reg1));
+#if !defined(WITH_SELF_VERIFICATION)
+ storeMultiple(cUnit, reg2, (1<<reg0 | 1<<reg1));
+#else
+ int regMap = reg1 << 8 | reg0 << 4 | reg2;
+ selfVerificationMemOpWrapper(cUnit, regMap,
+ &selfVerificationStoreDoubleword);
+#endif
break;
}
case OP_NEW_INSTANCE: {
@@ -1609,21 +2316,30 @@
(cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
assert(classPtr != NULL);
assert(classPtr->status & CLASS_INITIALIZED);
- if ((classPtr->accessFlags & (ACC_INTERFACE|ACC_ABSTRACT)) != 0) {
- /* It's going to throw, just let the interp. deal with it. */
- genInterpSingleStep(cUnit, mir);
- return false;
- }
+ /*
+ * If it is going to throw, it should not make to the trace to begin
+ * with.
+ */
+ assert((classPtr->accessFlags & (ACC_INTERFACE|ACC_ABSTRACT)) == 0);
loadConstant(cUnit, r4PC, (int)dvmAllocObject);
loadConstant(cUnit, r0, (int) classPtr);
genExportPC(cUnit, mir, r2, r3 );
loadConstant(cUnit, r1, ALLOC_DONT_TRACK);
- newLIR1(cUnit, THUMB_BLX_R, r4PC);
+ opReg(cUnit, OP_BLX, r4PC);
+ /* generate a branch over if allocation is successful */
+ opRegImm(cUnit, OP_CMP, r0, 0, rNone); /* NULL? */
+ ArmLIR *branchOver = opCondBranch(cUnit, ARM_COND_NE);
/*
- * TODO: As coded, we'll bail and reinterpret on alloc failure.
- * Need a general mechanism to bail to thrown exception code.
+ * OOM exception needs to be thrown here and cannot re-execute
*/
- genZeroCheck(cUnit, r0, mir->offset, NULL);
+ loadConstant(cUnit, r0,
+ (int) (cUnit->method->insns + mir->offset));
+ genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
+ /* noreturn */
+
+ ArmLIR *target = newLIR0(cUnit, ARM_PSEUDO_TARGET_LABEL);
+ target->defMask = ENCODE_ALL;
+ branchOver->generic.target = (LIR *) target;
storeValue(cUnit, r0, mir->dalvikInsn.vA, r1);
break;
}
@@ -1636,27 +2352,19 @@
(cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]);
loadConstant(cUnit, r1, (int) classPtr );
loadValue(cUnit, mir->dalvikInsn.vA, r0); /* Ref */
- /*
- * TODO - in theory classPtr should be resoved by the time this
- * instruction made into a trace, but we are seeing NULL at runtime
- * so this check is temporarily used as a workaround.
- */
- ArmLIR * pcrLabel = genZeroCheck(cUnit, r1, mir->offset, NULL);
- newLIR2(cUnit, THUMB_CMP_RI8, r0, 0); /* Null? */
- ArmLIR *branch1 =
- newLIR2(cUnit, THUMB_B_COND, 4, ARM_COND_EQ);
+ opRegImm(cUnit, OP_CMP, r0, 0, rNone); /* Null? */
+ ArmLIR *branch1 = opCondBranch(cUnit, ARM_COND_EQ);
/* r0 now contains object->clazz */
- newLIR3(cUnit, THUMB_LDR_RRI5, r0, r0,
- offsetof(Object, clazz) >> 2);
+ loadWordDisp(cUnit, r0, offsetof(Object, clazz), r0);
loadConstant(cUnit, r4PC, (int)dvmInstanceofNonTrivial);
- newLIR2(cUnit, THUMB_CMP_RR, r0, r1);
- ArmLIR *branch2 =
- newLIR2(cUnit, THUMB_B_COND, 2, ARM_COND_EQ);
- newLIR1(cUnit, THUMB_BLX_R, r4PC);
+ opRegReg(cUnit, OP_CMP, r0, r1);
+ ArmLIR *branch2 = opCondBranch(cUnit, ARM_COND_EQ);
+ opReg(cUnit, OP_BLX, r4PC);
/* check cast failed - punt to the interpreter */
- genZeroCheck(cUnit, r0, mir->offset, pcrLabel);
+ genZeroCheck(cUnit, r0, mir->offset, NULL);
/* check cast passed - branch target here */
ArmLIR *target = newLIR0(cUnit, ARM_PSEUDO_TARGET_LABEL);
+ target->defMask = ENCODE_ALL;
branch1->generic.target = (LIR *)target;
branch2->generic.target = (LIR *)target;
break;
@@ -1674,65 +2382,61 @@
case OP_MOVE_EXCEPTION: {
int offset = offsetof(InterpState, self);
int exOffset = offsetof(Thread, exception);
- newLIR3(cUnit, THUMB_LDR_RRI5, r1, rGLUE, offset >> 2);
- newLIR3(cUnit, THUMB_LDR_RRI5, r0, r1, exOffset >> 2);
+ loadWordDisp(cUnit, rGLUE, offset, r1);
+ loadWordDisp(cUnit, r1, exOffset, r0);
storeValue(cUnit, r0, mir->dalvikInsn.vA, r1);
break;
}
case OP_MOVE_RESULT:
case OP_MOVE_RESULT_OBJECT: {
int offset = offsetof(InterpState, retval);
- newLIR3(cUnit, THUMB_LDR_RRI5, r0, rGLUE, offset >> 2);
+ loadWordDisp(cUnit, rGLUE, offset, r0);
storeValue(cUnit, r0, mir->dalvikInsn.vA, r1);
break;
}
case OP_MOVE_RESULT_WIDE: {
int offset = offsetof(InterpState, retval);
- newLIR3(cUnit, THUMB_LDR_RRI5, r0, rGLUE, offset >> 2);
- newLIR3(cUnit, THUMB_LDR_RRI5, r1, rGLUE, (offset >> 2)+1);
+ loadWordDisp(cUnit, rGLUE, offset, r0);
+ loadWordDisp(cUnit, rGLUE, offset+4, r1);
storeValuePair(cUnit, r0, r1, mir->dalvikInsn.vA, r2);
break;
}
case OP_RETURN_WIDE: {
- loadValuePair(cUnit, mir->dalvikInsn.vA, r0, r1);
+ int vSrc = mir->dalvikInsn.vA;
+ int reg0 = selectFirstRegister(cUnit, vSrc, true);
+ int reg1 = NEXT_REG(reg0);
+ int rScratch = NEXT_REG(reg1);
int offset = offsetof(InterpState, retval);
- newLIR3(cUnit, THUMB_STR_RRI5, r0, rGLUE, offset >> 2);
- newLIR3(cUnit, THUMB_STR_RRI5, r1, rGLUE, (offset >> 2)+1);
+ loadValuePair(cUnit, vSrc, reg0, reg1);
+ storeWordDisp(cUnit, rGLUE, offset, reg0, rScratch);
+ storeWordDisp(cUnit, rGLUE, offset + 4, reg1, rScratch);
genReturnCommon(cUnit,mir);
break;
}
case OP_RETURN:
case OP_RETURN_OBJECT: {
- loadValue(cUnit, mir->dalvikInsn.vA, r0);
- int offset = offsetof(InterpState, retval);
- newLIR3(cUnit, THUMB_STR_RRI5, r0, rGLUE, offset >> 2);
+ int vSrc = mir->dalvikInsn.vA;
+ int reg0 = selectFirstRegister(cUnit, vSrc, false);
+ int rScratch = NEXT_REG(reg0);
+ loadValue(cUnit, vSrc, reg0);
+ storeWordDisp(cUnit, rGLUE, offsetof(InterpState, retval),
+ reg0, rScratch);
genReturnCommon(cUnit,mir);
break;
}
- /*
- * TODO-VERIFY: May be playing a bit fast and loose here. As coded,
- * a failure on lock/unlock will cause us to revert to the interpeter
- * to try again. This means we essentially ignore the first failure on
- * the assumption that the interpreter will correctly handle the 2nd.
- */
case OP_MONITOR_ENTER:
case OP_MONITOR_EXIT: {
int offset = offsetof(InterpState, self);
loadValue(cUnit, mir->dalvikInsn.vA, r1);
- newLIR3(cUnit, THUMB_LDR_RRI5, r0, rGLUE, offset >> 2);
+ loadWordDisp(cUnit, rGLUE, offset, r0);
if (dalvikOpCode == OP_MONITOR_ENTER) {
loadConstant(cUnit, r2, (int)dvmLockObject);
} else {
loadConstant(cUnit, r2, (int)dvmUnlockObject);
}
- /*
- * TODO-VERIFY: Note that we're not doing an EXPORT_PC, as
- * Lock/unlock won't throw, and this code does not support
- * DEADLOCK_PREDICTION or MONITOR_TRACKING. Should it?
- */
genNullCheck(cUnit, mir->dalvikInsn.vA, r1, mir->offset, NULL);
/* Do the call */
- newLIR1(cUnit, THUMB_BLX_R, r2);
+ opReg(cUnit, OP_BLX, r2);
break;
}
case OP_THROW: {
@@ -1757,6 +2461,8 @@
int __aeabi_d2iz( double op1 );
float __aeabi_l2f( long op1 );
double __aeabi_l2d( long op1 );
+ s8 dvmJitf2l( float op1 );
+ s8 dvmJitd2l( double op1 );
switch (opCode) {
case OP_INT_TO_FLOAT:
@@ -1792,8 +2498,6 @@
int vSrc2 = mir->dalvikInsn.vB;
int reg0, reg1, reg2;
- /* TODO - find the proper include file to declare these */
-
if ( (opCode >= OP_ADD_INT_2ADDR) && (opCode <= OP_REM_DOUBLE_2ADDR)) {
return genArithOp( cUnit, mir );
}
@@ -1843,7 +2547,7 @@
reg2 = NEXT_REG(reg1);
loadValue(cUnit, vSrc2, reg0);
- newLIR3(cUnit, THUMB_ASR, reg1, reg0, 31);
+ opRegRegImm(cUnit, OP_ASR, reg1, reg0, 31, rNone);
storeValuePair(cUnit, reg0, reg1, vSrc1Dest, reg2);
break;
}
@@ -1855,27 +2559,24 @@
break;
case OP_INT_TO_BYTE:
loadValue(cUnit, vSrc2, reg0);
- newLIR3(cUnit, THUMB_LSL, reg0, reg0, 24);
- newLIR3(cUnit, THUMB_ASR, reg0, reg0, 24);
- storeValue(cUnit, reg0, vSrc1Dest, reg1);
+ opRegReg(cUnit, OP_2BYTE, reg1, reg0);
+ storeValue(cUnit, reg1, vSrc1Dest, reg2);
break;
case OP_INT_TO_SHORT:
loadValue(cUnit, vSrc2, reg0);
- newLIR3(cUnit, THUMB_LSL, reg0, reg0, 16);
- newLIR3(cUnit, THUMB_ASR, reg0, reg0, 16);
- storeValue(cUnit, reg0, vSrc1Dest, reg1);
+ opRegReg(cUnit, OP_2SHORT, reg1, reg0);
+ storeValue(cUnit, reg1, vSrc1Dest, reg2);
break;
case OP_INT_TO_CHAR:
loadValue(cUnit, vSrc2, reg0);
- newLIR3(cUnit, THUMB_LSL, reg0, reg0, 16);
- newLIR3(cUnit, THUMB_LSR, reg0, reg0, 16);
- storeValue(cUnit, reg0, vSrc1Dest, reg1);
+ opRegReg(cUnit, OP_2CHAR, reg1, reg0);
+ storeValue(cUnit, reg1, vSrc1Dest, reg2);
break;
case OP_ARRAY_LENGTH: {
int lenOffset = offsetof(ArrayObject, length);
- loadValue(cUnit, vSrc2, reg0);
- genNullCheck(cUnit, vSrc2, reg0, mir->offset, NULL);
- newLIR3(cUnit, THUMB_LDR_RRI5, reg0, reg0, lenOffset >> 2);
+ loadValue(cUnit, vSrc2, reg1);
+ genNullCheck(cUnit, vSrc2, reg1, mir->offset, NULL);
+ loadWordDisp(cUnit, reg1, lenOffset, reg0);
storeValue(cUnit, reg0, vSrc1Dest, reg1);
break;
}
@@ -1900,7 +2601,7 @@
reg2 = NEXT_REG(reg1);
loadConstant(cUnit, reg0, BBBB);
- newLIR3(cUnit, THUMB_ASR, reg1, reg0, 31);
+ opRegRegImm(cUnit, OP_ASR, reg1, reg0, 31, rNone);
/* Save the long values to the specified Dalvik register pair */
storeValuePair(cUnit, reg0, reg1, vDest, reg2);
@@ -1928,8 +2629,9 @@
int reg0 = selectFirstRegister(cUnit, mir->dalvikInsn.vA, false);
loadValue(cUnit, mir->dalvikInsn.vA, reg0);
- newLIR2(cUnit, THUMB_CMP_RI8, reg0, 0);
+ opRegImm(cUnit, OP_CMP, reg0, 0, rNone);
+//TUNING: break this out to allow use of Thumb2 CB[N]Z
switch (dalvikOpCode) {
case OP_IF_EQZ:
cond = ARM_COND_EQ;
@@ -1966,14 +2668,13 @@
int vSrc = mir->dalvikInsn.vB;
int vDest = mir->dalvikInsn.vA;
int lit = mir->dalvikInsn.vC;
- int armOp;
+ OpKind op = 0; /* Make gcc happy */
int reg0, reg1, regDest;
reg0 = selectFirstRegister(cUnit, vSrc, false);
reg1 = NEXT_REG(reg0);
regDest = NEXT_REG(reg1);
- /* TODO: find the proper .h file to declare these */
int __aeabi_idivmod(int op1, int op2);
int __aeabi_idiv(int op1, int op2);
@@ -1981,31 +2682,16 @@
case OP_ADD_INT_LIT8:
case OP_ADD_INT_LIT16:
loadValue(cUnit, vSrc, reg0);
- if (lit <= 7 && lit >= 0) {
- newLIR3(cUnit, THUMB_ADD_RRI3, regDest, reg0, lit);
- storeValue(cUnit, regDest, vDest, reg1);
- } else if (lit <= 255 && lit >= 0) {
- newLIR2(cUnit, THUMB_ADD_RI8, reg0, lit);
- storeValue(cUnit, reg0, vDest, reg1);
- } else if (lit >= -7 && lit <= 0) {
- /* Convert to a small constant subtraction */
- newLIR3(cUnit, THUMB_SUB_RRI3, regDest, reg0, -lit);
- storeValue(cUnit, regDest, vDest, reg1);
- } else if (lit >= -255 && lit <= 0) {
- /* Convert to a small constant subtraction */
- newLIR2(cUnit, THUMB_SUB_RI8, reg0, -lit);
- storeValue(cUnit, reg0, vDest, reg1);
- } else {
- loadConstant(cUnit, reg1, lit);
- genBinaryOp(cUnit, vDest, THUMB_ADD_RRR, reg0, reg1, regDest);
- }
+ opRegImm(cUnit, OP_ADD, reg0, lit, reg1);
+ storeValue(cUnit, reg0, vDest, reg1);
break;
case OP_RSUB_INT_LIT8:
case OP_RSUB_INT:
loadValue(cUnit, vSrc, reg1);
loadConstant(cUnit, reg0, lit);
- genBinaryOp(cUnit, vDest, THUMB_SUB_RRR, reg0, reg1, regDest);
+ opRegRegReg(cUnit, OP_SUB, regDest, reg0, reg1);
+ storeValue(cUnit, regDest, vDest, reg1);
break;
case OP_MUL_INT_LIT8:
@@ -2017,28 +2703,28 @@
case OP_XOR_INT_LIT8:
case OP_XOR_INT_LIT16:
loadValue(cUnit, vSrc, reg0);
- loadConstant(cUnit, reg1, lit);
switch (dalvikOpCode) {
case OP_MUL_INT_LIT8:
case OP_MUL_INT_LIT16:
- armOp = THUMB_MUL;
+ op = OP_MUL;
break;
case OP_AND_INT_LIT8:
case OP_AND_INT_LIT16:
- armOp = THUMB_AND_RR;
+ op = OP_AND;
break;
case OP_OR_INT_LIT8:
case OP_OR_INT_LIT16:
- armOp = THUMB_ORR;
+ op = OP_OR;
break;
case OP_XOR_INT_LIT8:
case OP_XOR_INT_LIT16:
- armOp = THUMB_EOR;
+ op = OP_XOR;
break;
default:
dvmAbort();
}
- genBinaryOp(cUnit, vDest, armOp, reg0, reg1, regDest);
+ opRegRegImm(cUnit, op, regDest, reg0, lit, reg1);
+ storeValue(cUnit, regDest, vDest, reg1);
break;
case OP_SHL_INT_LIT8:
@@ -2047,18 +2733,22 @@
loadValue(cUnit, vSrc, reg0);
switch (dalvikOpCode) {
case OP_SHL_INT_LIT8:
- armOp = THUMB_LSL;
+ op = OP_LSL;
break;
case OP_SHR_INT_LIT8:
- armOp = THUMB_ASR;
+ op = OP_ASR;
break;
case OP_USHR_INT_LIT8:
- armOp = THUMB_LSR;
+ op = OP_LSR;
break;
default: dvmAbort();
}
- newLIR3(cUnit, armOp, reg0, reg0, lit);
- storeValue(cUnit, reg0, vDest, reg1);
+ if (lit != 0) {
+ opRegRegImm(cUnit, op, regDest, reg0, lit, reg1);
+ storeValue(cUnit, regDest, vDest, reg1);
+ } else {
+ storeValue(cUnit, reg0, vDest, reg1);
+ }
break;
case OP_DIV_INT_LIT8:
@@ -2072,7 +2762,7 @@
loadConstant(cUnit, r2, (int)__aeabi_idiv);
loadConstant(cUnit, r1, lit);
loadValue(cUnit, vSrc, r0);
- newLIR1(cUnit, THUMB_BLX_R, r2);
+ opReg(cUnit, OP_BLX, r2);
storeValue(cUnit, r0, vDest, r2);
break;
@@ -2087,7 +2777,7 @@
loadConstant(cUnit, r2, (int)__aeabi_idivmod);
loadConstant(cUnit, r1, lit);
loadValue(cUnit, vSrc, r0);
- newLIR1(cUnit, THUMB_BLX_R, r2);
+ opReg(cUnit, OP_BLX, r2);
storeValue(cUnit, r1, vDest, r2);
break;
default:
@@ -2104,19 +2794,14 @@
if (dalvikOpCode >= OP_IGET && dalvikOpCode <= OP_IPUT_SHORT) {
InstField *pInstField = (InstField *)
cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vC];
- int fieldOffset;
assert(pInstField != NULL);
fieldOffset = pInstField->byteOffset;
} else {
- /* To make the compiler happy */
- fieldOffset = 0;
+ /* Deliberately break the code while make the compiler happy */
+ fieldOffset = -1;
}
switch (dalvikOpCode) {
- /*
- * TODO: I may be assuming too much here.
- * Verify what is known at JIT time.
- */
case OP_NEW_ARRAY: {
void *classPtr = (void*)
(cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vC]);
@@ -2124,46 +2809,54 @@
loadValue(cUnit, mir->dalvikInsn.vB, r1); /* Len */
loadConstant(cUnit, r0, (int) classPtr );
loadConstant(cUnit, r4PC, (int)dvmAllocArrayByClass);
+ /*
+ * "len < 0": bail to the interpreter to re-execute the
+ * instruction
+ */
ArmLIR *pcrLabel =
genRegImmCheck(cUnit, ARM_COND_MI, r1, 0, mir->offset, NULL);
genExportPC(cUnit, mir, r2, r3 );
- newLIR2(cUnit, THUMB_MOV_IMM,r2,ALLOC_DONT_TRACK);
- newLIR1(cUnit, THUMB_BLX_R, r4PC);
+ loadConstant(cUnit, r2, ALLOC_DONT_TRACK);
+ opReg(cUnit, OP_BLX, r4PC);
+ /* generate a branch over if allocation is successful */
+ opRegImm(cUnit, OP_CMP, r0, 0, rNone); /* NULL? */
+ ArmLIR *branchOver = opCondBranch(cUnit, ARM_COND_NE);
/*
- * TODO: As coded, we'll bail and reinterpret on alloc failure.
- * Need a general mechanism to bail to thrown exception code.
+ * OOM exception needs to be thrown here and cannot re-execute
*/
- genZeroCheck(cUnit, r0, mir->offset, pcrLabel);
+ loadConstant(cUnit, r0,
+ (int) (cUnit->method->insns + mir->offset));
+ genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
+ /* noreturn */
+
+ ArmLIR *target = newLIR0(cUnit, ARM_PSEUDO_TARGET_LABEL);
+ target->defMask = ENCODE_ALL;
+ branchOver->generic.target = (LIR *) target;
storeValue(cUnit, r0, mir->dalvikInsn.vA, r1);
break;
}
- /*
- * TODO: I may be assuming too much here.
- * Verify what is known at JIT time.
- */
case OP_INSTANCE_OF: {
ClassObject *classPtr =
(cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vC]);
assert(classPtr != NULL);
loadValue(cUnit, mir->dalvikInsn.vB, r0); /* Ref */
loadConstant(cUnit, r2, (int) classPtr );
- newLIR2(cUnit, THUMB_CMP_RI8, r0, 0); /* Null? */
+//TUNING: compare to 0 primative to allow use of CB[N]Z
+ opRegImm(cUnit, OP_CMP, r0, 0, rNone); /* NULL? */
/* When taken r0 has NULL which can be used for store directly */
- ArmLIR *branch1 = newLIR2(cUnit, THUMB_B_COND, 4,
- ARM_COND_EQ);
+ ArmLIR *branch1 = opCondBranch(cUnit, ARM_COND_EQ);
/* r1 now contains object->clazz */
- newLIR3(cUnit, THUMB_LDR_RRI5, r1, r0,
- offsetof(Object, clazz) >> 2);
+ loadWordDisp(cUnit, r0, offsetof(Object, clazz), r1);
loadConstant(cUnit, r4PC, (int)dvmInstanceofNonTrivial);
loadConstant(cUnit, r0, 1); /* Assume true */
- newLIR2(cUnit, THUMB_CMP_RR, r1, r2);
- ArmLIR *branch2 = newLIR2(cUnit, THUMB_B_COND, 2,
- ARM_COND_EQ);
- newLIR2(cUnit, THUMB_MOV_RR, r0, r1);
- newLIR2(cUnit, THUMB_MOV_RR, r1, r2);
- newLIR1(cUnit, THUMB_BLX_R, r4PC);
+ opRegReg(cUnit, OP_CMP, r1, r2);
+ ArmLIR *branch2 = opCondBranch(cUnit, ARM_COND_EQ);
+ opRegReg(cUnit, OP_MOV, r0, r1);
+ opRegReg(cUnit, OP_MOV, r1, r2);
+ opReg(cUnit, OP_BLX, r4PC);
/* branch target here */
ArmLIR *target = newLIR0(cUnit, ARM_PSEUDO_TARGET_LABEL);
+ target->defMask = ENCODE_ALL;
storeValue(cUnit, r0, mir->dalvikInsn.vA, r1);
branch1->generic.target = (LIR *)target;
branch2->generic.target = (LIR *)target;
@@ -2174,34 +2867,34 @@
break;
case OP_IGET:
case OP_IGET_OBJECT:
- genIGet(cUnit, mir, THUMB_LDR_RRR, fieldOffset);
+ genIGet(cUnit, mir, WORD, fieldOffset);
break;
case OP_IGET_BOOLEAN:
- genIGet(cUnit, mir, THUMB_LDRB_RRR, fieldOffset);
+ genIGet(cUnit, mir, UNSIGNED_BYTE, fieldOffset);
break;
case OP_IGET_BYTE:
- genIGet(cUnit, mir, THUMB_LDRSB_RRR, fieldOffset);
+ genIGet(cUnit, mir, SIGNED_BYTE, fieldOffset);
break;
case OP_IGET_CHAR:
- genIGet(cUnit, mir, THUMB_LDRH_RRR, fieldOffset);
+ genIGet(cUnit, mir, UNSIGNED_HALF, fieldOffset);
break;
case OP_IGET_SHORT:
- genIGet(cUnit, mir, THUMB_LDRSH_RRR, fieldOffset);
+ genIGet(cUnit, mir, SIGNED_HALF, fieldOffset);
break;
case OP_IPUT_WIDE:
genIPutWide(cUnit, mir, fieldOffset);
break;
case OP_IPUT:
case OP_IPUT_OBJECT:
- genIPut(cUnit, mir, THUMB_STR_RRR, fieldOffset);
+ genIPut(cUnit, mir, WORD, fieldOffset);
break;
case OP_IPUT_SHORT:
case OP_IPUT_CHAR:
- genIPut(cUnit, mir, THUMB_STRH_RRR, fieldOffset);
+ genIPut(cUnit, mir, UNSIGNED_HALF, fieldOffset);
break;
case OP_IPUT_BYTE:
case OP_IPUT_BOOLEAN:
- genIPut(cUnit, mir, THUMB_STRB_RRR, fieldOffset);
+ genIPut(cUnit, mir, UNSIGNED_BYTE, fieldOffset);
break;
default:
return true;
@@ -2216,11 +2909,11 @@
switch (dalvikOpCode) {
case OP_IGET_QUICK:
case OP_IGET_OBJECT_QUICK:
- genIGet(cUnit, mir, THUMB_LDR_RRR, fieldOffset);
+ genIGet(cUnit, mir, WORD, fieldOffset);
break;
case OP_IPUT_QUICK:
case OP_IPUT_OBJECT_QUICK:
- genIPut(cUnit, mir, THUMB_STR_RRR, fieldOffset);
+ genIPut(cUnit, mir, WORD, fieldOffset);
break;
case OP_IGET_WIDE_QUICK:
genIGetWide(cUnit, mir, fieldOffset);
@@ -2256,7 +2949,7 @@
loadValue(cUnit, mir->dalvikInsn.vA, reg0);
loadValue(cUnit, mir->dalvikInsn.vB, reg1);
}
- newLIR2(cUnit, THUMB_CMP_RR, reg0, reg1);
+ opRegReg(cUnit, OP_CMP, reg0, reg1);
switch (dalvikOpCode) {
case OP_IF_EQ:
@@ -2340,44 +3033,41 @@
case OP_CMPG_DOUBLE:
return genCmpX(cUnit, mir, vA, vB, vC);
case OP_CMP_LONG:
- loadValuePair(cUnit,vB, r0, r1);
- loadValuePair(cUnit, vC, r2, r3);
- genDispatchToHandler(cUnit, TEMPLATE_CMP_LONG);
- storeValue(cUnit, r0, vA, r1);
+ genCmpLong(cUnit, mir, vA, vB, vC);
break;
case OP_AGET_WIDE:
- genArrayGet(cUnit, mir, THUMB_LDR_RRR, vB, vC, vA, 3);
+ genArrayGet(cUnit, mir, LONG, vB, vC, vA, 3);
break;
case OP_AGET:
case OP_AGET_OBJECT:
- genArrayGet(cUnit, mir, THUMB_LDR_RRR, vB, vC, vA, 2);
+ genArrayGet(cUnit, mir, WORD, vB, vC, vA, 2);
break;
case OP_AGET_BOOLEAN:
- genArrayGet(cUnit, mir, THUMB_LDRB_RRR, vB, vC, vA, 0);
+ genArrayGet(cUnit, mir, UNSIGNED_BYTE, vB, vC, vA, 0);
break;
case OP_AGET_BYTE:
- genArrayGet(cUnit, mir, THUMB_LDRSB_RRR, vB, vC, vA, 0);
+ genArrayGet(cUnit, mir, SIGNED_BYTE, vB, vC, vA, 0);
break;
case OP_AGET_CHAR:
- genArrayGet(cUnit, mir, THUMB_LDRH_RRR, vB, vC, vA, 1);
+ genArrayGet(cUnit, mir, UNSIGNED_HALF, vB, vC, vA, 1);
break;
case OP_AGET_SHORT:
- genArrayGet(cUnit, mir, THUMB_LDRSH_RRR, vB, vC, vA, 1);
+ genArrayGet(cUnit, mir, SIGNED_HALF, vB, vC, vA, 1);
break;
case OP_APUT_WIDE:
- genArrayPut(cUnit, mir, THUMB_STR_RRR, vB, vC, vA, 3);
+ genArrayPut(cUnit, mir, LONG, vB, vC, vA, 3);
break;
case OP_APUT:
case OP_APUT_OBJECT:
- genArrayPut(cUnit, mir, THUMB_STR_RRR, vB, vC, vA, 2);
+ genArrayPut(cUnit, mir, WORD, vB, vC, vA, 2);
break;
case OP_APUT_SHORT:
case OP_APUT_CHAR:
- genArrayPut(cUnit, mir, THUMB_STRH_RRR, vB, vC, vA, 1);
+ genArrayPut(cUnit, mir, UNSIGNED_HALF, vB, vC, vA, 1);
break;
case OP_APUT_BYTE:
case OP_APUT_BOOLEAN:
- genArrayPut(cUnit, mir, THUMB_STRB_RRR, vB, vC, vA, 0);
+ genArrayPut(cUnit, mir, UNSIGNED_BYTE, vB, vC, vA, 0);
break;
default:
return true;
@@ -2395,7 +3085,7 @@
loadConstant(cUnit, r1, (mir->dalvikInsn.vB << 1) +
(int) (cUnit->method->insns + mir->offset));
genExportPC(cUnit, mir, r2, r3 );
- newLIR1(cUnit, THUMB_BLX_R, r4PC);
+ opReg(cUnit, OP_BLX, r4PC);
genZeroCheck(cUnit, r0, mir->offset, NULL);
break;
}
@@ -2415,14 +3105,13 @@
loadValue(cUnit, mir->dalvikInsn.vA, r1);
loadConstant(cUnit, r0, (mir->dalvikInsn.vB << 1) +
(int) (cUnit->method->insns + mir->offset));
- newLIR1(cUnit, THUMB_BLX_R, r4PC);
+ opReg(cUnit, OP_BLX, r4PC);
loadConstant(cUnit, r1, (int)(cUnit->method->insns + mir->offset));
- newLIR3(cUnit, THUMB_LDR_RRI5, r2, rGLUE,
- offsetof(InterpState, jitToInterpEntries.dvmJitToInterpNoChain)
- >> 2);
- newLIR3(cUnit, THUMB_ADD_RRR, r0, r0, r0);
- newLIR3(cUnit, THUMB_ADD_RRR, r4PC, r0, r1);
- newLIR1(cUnit, THUMB_BLX_R, r2);
+ loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
+ jitToInterpEntries.dvmJitToInterpNoChain), r2);
+ opRegReg(cUnit, OP_ADD, r0, r0);
+ opRegRegReg(cUnit, OP_ADD, r4PC, r0, r1);
+ opReg(cUnit, OP_BLX, r2);
break;
}
default:
@@ -2527,6 +3216,11 @@
calleeMethod);
break;
}
+/*
+ * TODO: When we move to using upper registers in Thumb2, make sure
+ * the register allocater is told that r9, r10, & r12 are killed
+ * here.
+ */
/*
* calleeMethod = dvmFindInterfaceMethodInCache(this->clazz,
* BBBB, method, method->clazz->pDvmDex)
@@ -2608,13 +3302,13 @@
(int) (cUnit->method->insns + mir->offset));
/* r1 = &retChainingCell */
- ArmLIR *addrRetChain = newLIR2(cUnit, THUMB_ADD_PC_REL,
- r1, 0);
+ ArmLIR *addrRetChain =
+ opRegRegImm(cUnit, OP_ADD, r1, rpc, 0, rNone);
addrRetChain->generic.target = (LIR *) retChainingCell;
/* r2 = &predictedChainingCell */
ArmLIR *predictedChainingCell =
- newLIR2(cUnit, THUMB_ADD_PC_REL, r2, 0);
+ opRegRegImm(cUnit, OP_ADD, r2, rpc, 0, rNone);
predictedChainingCell->generic.target = (LIR *) predChainingCell;
genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN);
@@ -2649,12 +3343,12 @@
*/
/* Save count, &predictedChainCell, and class to high regs first */
- newLIR2(cUnit, THUMB_MOV_RR_L2H, r9 & THUMB_REG_MASK, r1);
- newLIR2(cUnit, THUMB_MOV_RR_L2H, r10 & THUMB_REG_MASK, r2);
- newLIR2(cUnit, THUMB_MOV_RR_L2H, r12 & THUMB_REG_MASK, r3);
+ opRegReg(cUnit, OP_MOV, r9, r1);
+ opRegReg(cUnit, OP_MOV, r10, r2);
+ opRegReg(cUnit, OP_MOV, r12, r3);
/* r0 now contains this->clazz */
- newLIR2(cUnit, THUMB_MOV_RR, r0, r3);
+ opRegReg(cUnit, OP_MOV, r0, r3);
/* r1 = BBBB */
loadConstant(cUnit, r1, dInsn->vB);
@@ -2667,25 +3361,22 @@
loadConstant(cUnit, r7,
(intptr_t) dvmFindInterfaceMethodInCache);
- newLIR1(cUnit, THUMB_BLX_R, r7);
+ opReg(cUnit, OP_BLX, r7);
/* r0 = calleeMethod (returned from dvmFindInterfaceMethodInCache */
- newLIR2(cUnit, THUMB_MOV_RR_H2L, r1, r9 & THUMB_REG_MASK);
+ opRegReg(cUnit, OP_MOV, r1, r9);
/* Check if rechain limit is reached */
- newLIR2(cUnit, THUMB_CMP_RI8, r1, 0);
+ opRegImm(cUnit, OP_CMP, r1, 0, rNone);
- ArmLIR *bypassRechaining =
- newLIR2(cUnit, THUMB_B_COND, 0, ARM_COND_GT);
+ ArmLIR *bypassRechaining = opCondBranch(cUnit, ARM_COND_GT);
- newLIR3(cUnit, THUMB_LDR_RRI5, r7, rGLUE,
- offsetof(InterpState,
- jitToInterpEntries.dvmJitToPatchPredictedChain)
- >> 2);
+ loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
+ jitToInterpEntries.dvmJitToPatchPredictedChain), r7);
- newLIR2(cUnit, THUMB_MOV_RR_H2L, r2, r10 & THUMB_REG_MASK);
- newLIR2(cUnit, THUMB_MOV_RR_H2L, r3, r12 & THUMB_REG_MASK);
+ opRegReg(cUnit, OP_MOV, r2, r10);
+ opRegReg(cUnit, OP_MOV, r3, r12);
/*
* r0 = calleeMethod
@@ -2696,11 +3387,10 @@
* when patching the chaining cell and will be clobbered upon
* returning so it will be reconstructed again.
*/
- newLIR1(cUnit, THUMB_BLX_R, r7);
+ opReg(cUnit, OP_BLX, r7);
/* r1 = &retChainingCell */
- addrRetChain = newLIR3(cUnit, THUMB_ADD_PC_REL,
- r1, 0, 0);
+ addrRetChain = opRegRegImm(cUnit, OP_ADD, r1, rpc, 0, rNone);
addrRetChain->generic.target = (LIR *) retChainingCell;
bypassRechaining->generic.target = (LIR *) addrRetChain;
@@ -2821,14 +3511,7 @@
else
break; /* Handle with C routine */
case INLINE_MATH_COS:
- if (genInlineCos(cUnit, mir))
- return false;
- else
- break; /* Handle with C routine */
case INLINE_MATH_SIN:
- if (genInlineSin(cUnit, mir))
- return false;
- else
break; /* Handle with C routine */
case INLINE_MATH_ABS_FLOAT:
return genInlinedAbsFloat(cUnit, mir);
@@ -2836,16 +3519,19 @@
return genInlinedAbsDouble(cUnit, mir);
case INLINE_STRING_COMPARETO:
case INLINE_STRING_EQUALS:
+ case INLINE_STRING_INDEXOF_I:
+ case INLINE_STRING_INDEXOF_II:
break;
default:
dvmAbort();
}
/* Materialize pointer to retval & push */
- newLIR2(cUnit, THUMB_MOV_RR, r4PC, rGLUE);
- newLIR2(cUnit, THUMB_ADD_RI8, r4PC, offset);
+ opRegReg(cUnit, OP_MOV, r4PC, rGLUE);
+ opRegImm(cUnit, OP_ADD, r4PC, offset, rNone);
+
/* Push r4 and (just to take up space) r5) */
- newLIR1(cUnit, THUMB_PUSH, (1<<r4PC | 1<<rFP));
+ opImm(cUnit, OP_PUSH, (1 << r4PC | 1 << rFP));
/* Get code pointer to inline routine */
loadConstant(cUnit, r4PC, (int)inLineTable[operation].func);
@@ -2858,10 +3544,10 @@
loadValue(cUnit, dInsn->arg[i], i);
}
/* Call inline routine */
- newLIR1(cUnit, THUMB_BLX_R, r4PC);
+ opReg(cUnit, OP_BLX, r4PC);
/* Strip frame */
- newLIR1(cUnit, THUMB_ADD_SPI7, 2);
+ opRegImm(cUnit, OP_ADD, r13, 8, rNone);
/* Did we throw? If so, redo under interpreter*/
genZeroCheck(cUnit, r0, mir->offset, NULL);
@@ -2883,7 +3569,6 @@
return false;
}
-/*****************************************************************************/
/*
* The following are special processing routines that handle transfer of
* controls between compiled code and the interpreter. Certain VM states like
@@ -2894,9 +3579,9 @@
static void handleNormalChainingCell(CompilationUnit *cUnit,
unsigned int offset)
{
- newLIR3(cUnit, THUMB_LDR_RRI5, r0, rGLUE,
- offsetof(InterpState, jitToInterpEntries.dvmJitToInterpNormal) >> 2);
- newLIR1(cUnit, THUMB_BLX_R, r0);
+ loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
+ jitToInterpEntries.dvmJitToInterpNormal), r0);
+ opReg(cUnit, OP_BLX, r0);
addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
}
@@ -2907,19 +3592,36 @@
static void handleHotChainingCell(CompilationUnit *cUnit,
unsigned int offset)
{
+ loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
+ jitToInterpEntries.dvmJitToTraceSelect), r0);
+ opReg(cUnit, OP_BLX, r0);
+ addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
+}
+
+#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
+/* Chaining cell for branches that branch back into the same basic block */
+static void handleBackwardBranchChainingCell(CompilationUnit *cUnit,
+ unsigned int offset)
+{
+#if defined(WITH_SELF_VERIFICATION)
newLIR3(cUnit, THUMB_LDR_RRI5, r0, rGLUE,
- offsetof(InterpState, jitToInterpEntries.dvmJitToTraceSelect) >> 2);
+ offsetof(InterpState, jitToInterpEntries.dvmJitToBackwardBranch) >> 2);
+#else
+ newLIR3(cUnit, THUMB_LDR_RRI5, r0, rGLUE,
+ offsetof(InterpState, jitToInterpEntries.dvmJitToInterpNormal) >> 2);
+#endif
newLIR1(cUnit, THUMB_BLX_R, r0);
addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
}
+#endif
/* Chaining cell for monomorphic method invocations. */
static void handleInvokeSingletonChainingCell(CompilationUnit *cUnit,
const Method *callee)
{
- newLIR3(cUnit, THUMB_LDR_RRI5, r0, rGLUE,
- offsetof(InterpState, jitToInterpEntries.dvmJitToTraceSelect) >> 2);
- newLIR1(cUnit, THUMB_BLX_R, r0);
+ loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
+ jitToInterpEntries.dvmJitToTraceSelect), r0);
+ opReg(cUnit, OP_BLX, r0);
addWordData(cUnit, (int) (callee->insns), true);
}
@@ -2956,7 +3658,185 @@
}
}
-/* Entry function to invoke the backend of the JIT compiler */
+static char *extendedMIROpNames[MIR_OP_LAST - MIR_OP_FIRST] = {
+ "MIR_OP_PHI",
+ "MIR_OP_NULL_N_RANGE_UP_CHECK",
+ "MIR_OP_NULL_N_RANGE_DOWN_CHECK",
+ "MIR_OP_LOWER_BOUND_CHECK",
+ "MIR_OP_PUNT",
+};
+
+/*
+ * vA = arrayReg;
+ * vB = idxReg;
+ * vC = endConditionReg;
+ * arg[0] = maxC
+ * arg[1] = minC
+ * arg[2] = loopBranchConditionCode
+ */
+static void genHoistedChecksForCountUpLoop(CompilationUnit *cUnit, MIR *mir)
+{
+ DecodedInstruction *dInsn = &mir->dalvikInsn;
+ const int lenOffset = offsetof(ArrayObject, length);
+ const int regArray = 0;
+ const int regIdxEnd = NEXT_REG(regArray);
+ const int regLength = regArray;
+ const int maxC = dInsn->arg[0];
+ const int minC = dInsn->arg[1];
+
+ /* regArray <- arrayRef */
+ loadValue(cUnit, mir->dalvikInsn.vA, regArray);
+ loadValue(cUnit, mir->dalvikInsn.vC, regIdxEnd);
+ genRegImmCheck(cUnit, ARM_COND_EQ, regArray, 0, 0,
+ (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
+
+ /* regLength <- len(arrayRef) */
+ loadWordDisp(cUnit, regArray, lenOffset, regLength);
+
+ int delta = maxC;
+ /*
+ * If the loop end condition is ">=" instead of ">", then the largest value
+ * of the index is "endCondition - 1".
+ */
+ if (dInsn->arg[2] == OP_IF_GE) {
+ delta--;
+ }
+
+ if (delta) {
+ opRegImm(cUnit, OP_ADD, regIdxEnd, delta, regIdxEnd);
+ }
+ /* Punt if "regIdxEnd < len(Array)" is false */
+ genRegRegCheck(cUnit, ARM_COND_GE, regIdxEnd, regLength, 0,
+ (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
+}
+
+/*
+ * vA = arrayReg;
+ * vB = idxReg;
+ * vC = endConditionReg;
+ * arg[0] = maxC
+ * arg[1] = minC
+ * arg[2] = loopBranchConditionCode
+ */
+static void genHoistedChecksForCountDownLoop(CompilationUnit *cUnit, MIR *mir)
+{
+ DecodedInstruction *dInsn = &mir->dalvikInsn;
+ const int lenOffset = offsetof(ArrayObject, length);
+ const int regArray = 0;
+ const int regIdxInit = NEXT_REG(regArray);
+ const int regLength = regArray;
+ const int maxC = dInsn->arg[0];
+ const int minC = dInsn->arg[1];
+
+ /* regArray <- arrayRef */
+ loadValue(cUnit, mir->dalvikInsn.vA, regArray);
+ loadValue(cUnit, mir->dalvikInsn.vB, regIdxInit);
+ genRegImmCheck(cUnit, ARM_COND_EQ, regArray, 0, 0,
+ (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
+
+ /* regLength <- len(arrayRef) */
+ loadWordDisp(cUnit, regArray, lenOffset, regLength);
+
+ if (maxC) {
+ opRegImm(cUnit, OP_ADD, regIdxInit, maxC, regIdxInit);
+ }
+
+ /* Punt if "regIdxInit < len(Array)" is false */
+ genRegRegCheck(cUnit, ARM_COND_GE, regIdxInit, regLength, 0,
+ (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
+}
+
+/*
+ * vA = idxReg;
+ * vB = minC;
+ */
+static void genHoistedLowerBoundCheck(CompilationUnit *cUnit, MIR *mir)
+{
+ DecodedInstruction *dInsn = &mir->dalvikInsn;
+ const int regIdx = 0;
+ const int minC = dInsn->vB;
+
+ /* regIdx <- initial index value */
+ loadValue(cUnit, mir->dalvikInsn.vA, regIdx);
+
+ /* Punt if "regIdxInit + minC >= 0" is false */
+ genRegImmCheck(cUnit, ARM_COND_LT, regIdx, -minC, 0,
+ (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
+}
+
+/* Extended MIR instructions like PHI */
+static void handleExtendedMIR(CompilationUnit *cUnit, MIR *mir)
+{
+ int opOffset = mir->dalvikInsn.opCode - MIR_OP_FIRST;
+ char *msg = dvmCompilerNew(strlen(extendedMIROpNames[opOffset]) + 1,
+ false);
+ strcpy(msg, extendedMIROpNames[opOffset]);
+ newLIR1(cUnit, ARM_PSEUDO_EXTENDED_MIR, (int) msg);
+
+ switch (mir->dalvikInsn.opCode) {
+ case MIR_OP_PHI: {
+ char *ssaString = dvmCompilerGetSSAString(cUnit, mir->ssaRep);
+ newLIR1(cUnit, ARM_PSEUDO_SSA_REP, (int) ssaString);
+ break;
+ }
+ case MIR_OP_NULL_N_RANGE_UP_CHECK: {
+ genHoistedChecksForCountUpLoop(cUnit, mir);
+ break;
+ }
+ case MIR_OP_NULL_N_RANGE_DOWN_CHECK: {
+ genHoistedChecksForCountDownLoop(cUnit, mir);
+ break;
+ }
+ case MIR_OP_LOWER_BOUND_CHECK: {
+ genHoistedLowerBoundCheck(cUnit, mir);
+ break;
+ }
+ case MIR_OP_PUNT: {
+ genUnconditionalBranch(cUnit,
+ (ArmLIR *) cUnit->loopAnalysis->branchToPCR);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+/*
+ * Create a PC-reconstruction cell for the starting offset of this trace.
+ * Since the PCR cell is placed near the end of the compiled code which is
+ * usually out of range for a conditional branch, we put two branches (one
+ * branch over to the loop body and one layover branch to the actual PCR) at the
+ * end of the entry block.
+ */
+static void setupLoopEntryBlock(CompilationUnit *cUnit, BasicBlock *entry,
+ ArmLIR *bodyLabel)
+{
+ /* Set up the place holder to reconstruct this Dalvik PC */
+ ArmLIR *pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true);
+ pcrLabel->opCode = ARM_PSEUDO_PC_RECONSTRUCTION_CELL;
+ pcrLabel->operands[0] =
+ (int) (cUnit->method->insns + entry->startOffset);
+ pcrLabel->operands[1] = entry->startOffset;
+ /* Insert the place holder to the growable list */
+ dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
+
+ /*
+ * Next, create two branches - one branch over to the loop body and the
+ * other branch to the PCR cell to punt.
+ */
+ ArmLIR *branchToBody = dvmCompilerNew(sizeof(ArmLIR), true);
+ branchToBody->opCode = THUMB_B_UNCOND;
+ branchToBody->generic.target = (LIR *) bodyLabel;
+ setupResourceMasks(branchToBody);
+ cUnit->loopAnalysis->branchToBody = (LIR *) branchToBody;
+
+ ArmLIR *branchToPCR = dvmCompilerNew(sizeof(ArmLIR), true);
+ branchToPCR->opCode = THUMB_B_UNCOND;
+ branchToPCR->generic.target = (LIR *) pcrLabel;
+ setupResourceMasks(branchToPCR);
+ cUnit->loopAnalysis->branchToPCR = (LIR *) branchToPCR;
+}
+
void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
{
/* Used to hold the labels of each block */
@@ -2995,7 +3875,8 @@
cUnit->chainCellOffsetLIR =
(LIR *) newLIR1(cUnit, ARM_16BIT_DATA, CHAIN_CELL_OFFSET_TAG);
cUnit->headerSize = 6;
- newLIR2(cUnit, THUMB_MOV_RR_H2L, r0, rpc & THUMB_REG_MASK);
+ /* Thumb instruction used directly here to ensure correct size */
+ newLIR2(cUnit, THUMB_MOV_RR_H2L, r0, rpc);
newLIR2(cUnit, THUMB_SUB_RI8, r0, 10);
newLIR3(cUnit, THUMB_LDR_RRI5, r1, r0, 0);
newLIR2(cUnit, THUMB_ADD_RI8, r1, 1);
@@ -3022,7 +3903,18 @@
dvmCompilerAppendLIR(cUnit, (LIR *) &labelList[i]);
}
- if (blockList[i]->blockType == DALVIK_BYTECODE) {
+ if (blockList[i]->blockType == ENTRY_BLOCK) {
+ labelList[i].opCode = ARM_PSEUDO_ENTRY_BLOCK;
+ if (blockList[i]->firstMIRInsn == NULL) {
+ continue;
+ } else {
+ setupLoopEntryBlock(cUnit, blockList[i],
+ &labelList[blockList[i]->fallThrough->id]);
+ }
+ } else if (blockList[i]->blockType == EXIT_BLOCK) {
+ labelList[i].opCode = ARM_PSEUDO_EXIT_BLOCK;
+ goto gen_fallthrough;
+ } else if (blockList[i]->blockType == DALVIK_BYTECODE) {
labelList[i].opCode = ARM_PSEUDO_NORMAL_BLOCK_LABEL;
/* Reset the register state */
resetRegisterScoreboard(cUnit);
@@ -3070,13 +3962,22 @@
case EXCEPTION_HANDLING:
labelList[i].opCode = ARM_PSEUDO_EH_BLOCK_LABEL;
if (cUnit->pcReconstructionList.numUsed) {
- newLIR3(cUnit, THUMB_LDR_RRI5, r1, rGLUE,
- offsetof(InterpState,
- jitToInterpEntries.dvmJitToInterpPunt)
- >> 2);
- newLIR1(cUnit, THUMB_BLX_R, r1);
+ loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
+ jitToInterpEntries.dvmJitToInterpPunt),
+ r1);
+ opReg(cUnit, OP_BLX, r1);
}
break;
+#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
+ case CHAINING_CELL_BACKWARD_BRANCH:
+ labelList[i].opCode =
+ ARM_PSEUDO_CHAINING_CELL_BACKWARD_BRANCH;
+ /* handle the codegen later */
+ dvmInsertGrowableList(
+ &chainingListByType[CHAINING_CELL_BACKWARD_BRANCH],
+ (void *) i);
+ break;
+#endif
default:
break;
}
@@ -3086,16 +3987,29 @@
ArmLIR *headLIR = NULL;
for (mir = blockList[i]->firstMIRInsn; mir; mir = mir->next) {
+ if (mir->dalvikInsn.opCode >= MIR_OP_FIRST) {
+ handleExtendedMIR(cUnit, mir);
+ continue;
+ }
+
OpCode dalvikOpCode = mir->dalvikInsn.opCode;
InstructionFormat dalvikFormat =
dexGetInstrFormat(gDvm.instrFormat, dalvikOpCode);
ArmLIR *boundaryLIR =
newLIR2(cUnit, ARM_PSEUDO_DALVIK_BYTECODE_BOUNDARY,
- mir->offset,dalvikOpCode);
+ mir->offset, dalvikOpCode);
+ if (mir->ssaRep) {
+ char *ssaString = dvmCompilerGetSSAString(cUnit, mir->ssaRep);
+ newLIR1(cUnit, ARM_PSEUDO_SSA_REP, (int) ssaString);
+ }
+
/* Remember the first LIR for this block */
if (headLIR == NULL) {
headLIR = boundaryLIR;
+ /* Set the first boundaryLIR as a scheduling barrier */
+ headLIR->defMask = ENCODE_ALL;
}
+
bool notHandled;
/*
* Debugging: screen the opcode first to see if it is in the
@@ -3106,6 +4020,11 @@
((gDvmJit.opList[dalvikOpCode >> 3] &
(1 << (dalvikOpCode & 0x7))) !=
0);
+#if defined(WITH_SELF_VERIFICATION)
+ /* Punt on opcodes we can't replay */
+ if (selfVerificationPuntOps(dalvikOpCode))
+ singleStepMe = true;
+#endif
if (singleStepMe || cUnit->allSingleStep) {
notHandled = false;
genInterpSingleStep(cUnit, mir);
@@ -3202,9 +4121,24 @@
break;
}
}
- /* Eliminate redundant loads/stores and delay stores into later slots */
- dvmCompilerApplyLocalOptimizations(cUnit, (LIR *) headLIR,
- cUnit->lastLIRInsn);
+
+ if (blockList[i]->blockType == ENTRY_BLOCK) {
+ dvmCompilerAppendLIR(cUnit,
+ (LIR *) cUnit->loopAnalysis->branchToBody);
+ dvmCompilerAppendLIR(cUnit,
+ (LIR *) cUnit->loopAnalysis->branchToPCR);
+ }
+
+ if (headLIR) {
+ /*
+ * Eliminate redundant loads/stores and delay stores into later
+ * slots
+ */
+ dvmCompilerApplyLocalOptimizations(cUnit, (LIR *) headLIR,
+ cUnit->lastLIRInsn);
+ }
+
+gen_fallthrough:
/*
* Check if the block is terminated due to trace length constraint -
* insert an unconditional branch to the chaining cell.
@@ -3256,6 +4190,12 @@
handleHotChainingCell(cUnit,
blockList[blockId]->startOffset);
break;
+#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
+ case CHAINING_CELL_BACKWARD_BRANCH:
+ handleBackwardBranchChainingCell(cUnit,
+ blockList[blockId]->startOffset);
+ break;
+#endif
default:
dvmAbort();
break;
@@ -3335,3 +4275,19 @@
LOGD("dalvik.vm.jit.op = %s", buf);
}
}
+
+/* Common initialization routine for an architecture family */
+bool dvmCompilerArchInit()
+{
+ int i;
+
+ for (i = 0; i < ARM_LAST; i++) {
+ if (EncodingMap[i].opCode != i) {
+ LOGE("Encoding order for %s is wrong: expecting %d, seeing %d",
+ EncodingMap[i].name, i, EncodingMap[i].opCode);
+ dvmAbort();
+ }
+ }
+
+ return compilerArchVariantInit();
+}
diff --git a/vm/compiler/codegen/arm/Codegen.h b/vm/compiler/codegen/arm/Codegen.h
index 4016075..b484cd2 100644
--- a/vm/compiler/codegen/arm/Codegen.h
+++ b/vm/compiler/codegen/arm/Codegen.h
@@ -22,6 +22,8 @@
* variant code such as ThumbUtilty.c
*/
+static void annotateDalvikRegAccess(ArmLIR *lir, int regId, bool isLoad);
+static void setupResourceMasks(ArmLIR *lir);
static ArmLIR *newLIR0(CompilationUnit *cUnit, ArmOpCode opCode);
static ArmLIR *newLIR1(CompilationUnit *cUnit, ArmOpCode opCode,
int dest);
@@ -29,18 +31,18 @@
int dest, int src1);
static ArmLIR *newLIR3(CompilationUnit *cUnit, ArmOpCode opCode,
int dest, int src1, int src2);
-static ArmLIR *newLIR23(CompilationUnit *cUnit, ArmOpCode opCode,
- int srcdest, int src2);
+static ArmLIR *newLIR4(CompilationUnit *cUnit, ArmOpCode opCode,
+ int dest, int src1, int src2, int info);
static ArmLIR *scanLiteralPool(CompilationUnit *cUnit, int value,
unsigned int delta);
static ArmLIR *addWordData(CompilationUnit *cUnit, int value, bool inPlace);
static inline ArmLIR *genCheckCommon(CompilationUnit *cUnit, int dOffset,
ArmLIR *branch,
ArmLIR *pcrLabel);
+static void genBarrier(CompilationUnit *cUnit);
/* Routines which must be supplied by the variant-specific code */
static void genDispatchToHandler(CompilationUnit *cUnit, TemplateOpCode opCode);
-bool dvmCompilerArchInit(void);
static bool genInlineSqrt(CompilationUnit *cUnit, MIR *mir);
static bool genInlineCos(CompilationUnit *cUnit, MIR *mir);
static bool genInlineSin(CompilationUnit *cUnit, MIR *mir);
@@ -51,7 +53,6 @@
int vSrc1, int vSrc2);
static bool genCmpX(CompilationUnit *cUnit, MIR *mir, int vDest, int vSrc1,
int vSrc2);
-
-
+static bool compilerArchVariantInit();
#endif /* _DALVIK_VM_COMPILER_CODEGEN_ARM_CODEGEN_H */
diff --git a/vm/compiler/codegen/arm/GlobalOptimizations.c b/vm/compiler/codegen/arm/GlobalOptimizations.c
index 40e1f07..687b7d2 100644
--- a/vm/compiler/codegen/arm/GlobalOptimizations.c
+++ b/vm/compiler/codegen/arm/GlobalOptimizations.c
@@ -48,8 +48,7 @@
/*
* Found real useful stuff between the branch and the target
*/
- if (!isPseudoOpCode(nextLIR->opCode) ||
- nextLIR->opCode == ARM_PSEUDO_ALIGN4)
+ if (!isPseudoOpCode(nextLIR->opCode))
break;
}
}
diff --git a/vm/compiler/codegen/arm/LocalOptimizations.c b/vm/compiler/codegen/arm/LocalOptimizations.c
index 11aaedd..86f692f 100644
--- a/vm/compiler/codegen/arm/LocalOptimizations.c
+++ b/vm/compiler/codegen/arm/LocalOptimizations.c
@@ -18,25 +18,37 @@
#include "vm/compiler/CompilerInternals.h"
#include "ArmLIR.h"
+#define DEBUG_OPT(X)
+
ArmLIR* dvmCompilerGenCopy(CompilationUnit *cUnit, int rDest, int rSrc);
/* Is this a Dalvik register access? */
static inline bool isDalvikLoad(ArmLIR *lir)
{
- return ((lir->operands[1] == rFP) &&
- ((lir->opCode == THUMB_LDR_RRI5) ||
- (lir->opCode == THUMB2_LDR_RRI12) ||
- (lir->opCode == THUMB2_VLDRS) ||
- (lir->opCode == THUMB2_VLDRD)));
+ return (lir->useMask != ~0ULL) && (lir->useMask & ENCODE_DALVIK_REG);
}
static inline bool isDalvikStore(ArmLIR *lir)
{
- return ((lir->operands[1] == rFP) &&
- ((lir->opCode == THUMB_STR_RRI5) ||
- (lir->opCode == THUMB2_STR_RRI12) ||
- (lir->opCode == THUMB2_VSTRS) ||
- (lir->opCode == THUMB2_VSTRD)));
+ return (lir->defMask != ~0ULL) && (lir->defMask & ENCODE_DALVIK_REG);
+}
+
+static inline bool isDalvikRegisterClobbered(ArmLIR *lir1, ArmLIR *lir2)
+{
+ int reg1Lo = DECODE_ALIAS_INFO_REG(lir1->aliasInfo);
+ int reg1Hi = reg1Lo + DECODE_ALIAS_INFO_WIDE(lir1->aliasInfo);
+ int reg2Lo = DECODE_ALIAS_INFO_REG(lir2->aliasInfo);
+ int reg2Hi = reg2Lo + DECODE_ALIAS_INFO_WIDE(lir2->aliasInfo);
+
+ return (reg1Lo == reg2Lo) || (reg1Lo == reg2Hi) || (reg1Hi == reg2Lo);
+}
+
+static void dumpDependentInsnPair(ArmLIR *thisLIR, ArmLIR *checkLIR,
+ const char *optimization)
+{
+ LOGD("************ %s ************", optimization);
+ dvmDumpLIRInsn((LIR *) thisLIR, 0);
+ dvmDumpLIRInsn((LIR *) checkLIR, 0);
}
/*
@@ -59,10 +71,18 @@
continue;
}
if (isDalvikStore(thisLIR)) {
- int dRegId = thisLIR->operands[2];
+ int dRegId = DECODE_ALIAS_INFO_REG(thisLIR->aliasInfo);
+ int dRegIdHi = dRegId + DECODE_ALIAS_INFO_WIDE(thisLIR->aliasInfo);
int nativeRegId = thisLIR->operands[0];
ArmLIR *checkLIR;
int sinkDistance = 0;
+ /*
+ * Add r15 (pc) to the mask to prevent this instruction
+ * from sinking past branch instructions. Unset the Dalvik register
+ * bit when checking with native resource constraints.
+ */
+ u8 stopMask = (ENCODE_REG_PC | thisLIR->useMask) &
+ ~ENCODE_DALVIK_REG;
for (checkLIR = NEXT_LIR(thisLIR);
checkLIR != tailLIR;
@@ -70,10 +90,8 @@
/* Check if a Dalvik register load is redundant */
if (isDalvikLoad(checkLIR) &&
- checkLIR->operands[2] == dRegId ) {
- if (FPREG(nativeRegId) != FPREG(checkLIR->operands[0])) {
- break; // TODO: handle gen<=>float copies
- }
+ (checkLIR->aliasInfo == thisLIR->aliasInfo) &&
+ (REGTYPE(checkLIR->operands[0]) == REGTYPE(nativeRegId))) {
/* Insert a move to replace the load */
if (checkLIR->operands[0] != nativeRegId) {
ArmLIR *moveLIR;
@@ -90,44 +108,33 @@
checkLIR->isNop = true;
continue;
- /* Found a true output dependency - nuke the previous store */
+ /*
+ * Found a true output dependency - nuke the previous store.
+ * The register type doesn't matter here.
+ */
} else if (isDalvikStore(checkLIR) &&
- checkLIR->operands[2] == dRegId) {
+ (checkLIR->aliasInfo == thisLIR->aliasInfo)) {
thisLIR->isNop = true;
break;
/* Find out the latest slot that the store can be sunk into */
} else {
- bool stopHere = false;
-
/* Last instruction reached */
- stopHere |= checkLIR->generic.next == NULL;
+ bool stopHere = (NEXT_LIR(checkLIR) == tailLIR);
- /*
- * Conservatively assume there is a memory dependency
- * for st/ld multiples and reg+reg address mode
- */
- stopHere |= checkLIR->opCode == THUMB_STMIA ||
- checkLIR->opCode == THUMB_LDMIA ||
- checkLIR->opCode == THUMB_STR_RRR ||
- checkLIR->opCode == THUMB_LDR_RRR ||
- checkLIR->opCode == THUMB2_VLDRD ||
- checkLIR->opCode == THUMB2_VSTRD;
-;
+ /* Store data is clobbered */
+ stopHere |= ((stopMask & checkLIR->defMask) != 0);
- if (!isPseudoOpCode(checkLIR->opCode)) {
-
- /* Store data is clobbered */
- stopHere |= (EncodingMap[checkLIR->opCode].flags &
- CLOBBER_DEST) != 0 &&
- checkLIR->operands[0] == nativeRegId;
-
- stopHere |= (EncodingMap[checkLIR->opCode].flags &
- IS_BRANCH) != 0;
+ /* Store data partially clobbers the Dalvik register */
+ if (stopHere == false &&
+ ((checkLIR->useMask | checkLIR->defMask) &
+ ENCODE_DALVIK_REG)) {
+ stopHere = isDalvikRegisterClobbered(thisLIR, checkLIR);
}
/* Found a new place to put the store - move it here */
if (stopHere == true) {
-
+ DEBUG_OPT(dumpDependentInsnPair(thisLIR, checkLIR,
+ "SINK STORE"));
/* The store can be sunk for at least one cycle */
if (sinkDistance != 0) {
ArmLIR *newStoreLIR =
@@ -157,10 +164,186 @@
}
}
+static void applyLoadHoisting(CompilationUnit *cUnit,
+ ArmLIR *headLIR,
+ ArmLIR *tailLIR)
+{
+ ArmLIR *thisLIR;
+
+ cUnit->optRound++;
+ for (thisLIR = headLIR;
+ thisLIR != tailLIR;
+ thisLIR = NEXT_LIR(thisLIR)) {
+ /* Skip newly added instructions */
+ if (thisLIR->age >= cUnit->optRound ||
+ thisLIR->isNop == true) {
+ continue;
+ }
+ if (isDalvikLoad(thisLIR)) {
+ int dRegId = DECODE_ALIAS_INFO_REG(thisLIR->aliasInfo);
+ int dRegIdHi = dRegId + DECODE_ALIAS_INFO_WIDE(thisLIR->aliasInfo);
+ int nativeRegId = thisLIR->operands[0];
+ ArmLIR *checkLIR;
+ int hoistDistance = 0;
+ u8 stopUseMask = (ENCODE_REG_PC | thisLIR->useMask) &
+ ~ENCODE_DALVIK_REG;
+ u8 stopDefMask = thisLIR->defMask & ~ENCODE_DALVIK_REG;
+
+ /* First check if the load can be completely elinimated */
+ for (checkLIR = PREV_LIR(thisLIR);
+ checkLIR != headLIR;
+ checkLIR = PREV_LIR(checkLIR)) {
+
+ if (checkLIR->isNop) continue;
+
+ /*
+ * Check if the Dalvik register is previously accessed
+ * with exactly the same type.
+ */
+ if ((isDalvikLoad(checkLIR) || isDalvikStore(checkLIR)) &&
+ (checkLIR->aliasInfo == thisLIR->aliasInfo) &&
+ (checkLIR->operands[0] == nativeRegId)) {
+ /*
+ * If it is previously accessed but with a different type,
+ * the search will terminate later at the point checking
+ * for partially overlapping stores.
+ */
+ thisLIR->isNop = true;
+ break;
+ }
+
+ /*
+ * No earlier use/def can reach this load if:
+ * 1) Head instruction is reached
+ * 2) load target register is clobbered
+ * 3) A branch is seen (stopUseMask has the PC bit set).
+ */
+ if ((checkLIR == headLIR) ||
+ (stopUseMask | stopDefMask) & checkLIR->defMask) {
+ break;
+ }
+
+ /* Store data partially clobbers the Dalvik register */
+ if (isDalvikStore(checkLIR) &&
+ isDalvikRegisterClobbered(thisLIR, checkLIR)) {
+ break;
+ }
+ }
+
+ /* The load has been eliminated */
+ if (thisLIR->isNop) continue;
+
+ /*
+ * The load cannot be eliminated. See if it can be hoisted to an
+ * earlier spot.
+ */
+ for (checkLIR = PREV_LIR(thisLIR);
+ /* empty by intention */;
+ checkLIR = PREV_LIR(checkLIR)) {
+
+ if (checkLIR->isNop) continue;
+
+ /* Check if the current load is redundant */
+ if ((isDalvikLoad(checkLIR) || isDalvikStore(checkLIR)) &&
+ (checkLIR->aliasInfo == thisLIR->aliasInfo) &&
+ (REGTYPE(checkLIR->operands[0]) == REGTYPE(nativeRegId))) {
+ /* Insert a move to replace the load */
+ if (checkLIR->operands[0] != nativeRegId) {
+ ArmLIR *moveLIR;
+ moveLIR = dvmCompilerRegCopy(cUnit,
+ nativeRegId,
+ checkLIR->operands[0]);
+ /*
+ * Convert *thisLIR* load into a move
+ */
+ dvmCompilerInsertLIRAfter((LIR *) checkLIR,
+ (LIR *) moveLIR);
+ }
+ thisLIR->isNop = true;
+ break;
+
+ /* Find out if the load can be yanked past the checkLIR */
+ } else {
+ /* Last instruction reached */
+ bool stopHere = (checkLIR == headLIR);
+
+ /* Base address is clobbered by checkLIR */
+ stopHere |= ((stopUseMask & checkLIR->defMask) != 0);
+
+ /* Load target clobbers use/def in checkLIR */
+ stopHere |= ((stopDefMask &
+ (checkLIR->useMask | checkLIR->defMask)) != 0);
+
+ /* Store data partially clobbers the Dalvik register */
+ if (stopHere == false &&
+ (checkLIR->defMask & ENCODE_DALVIK_REG)) {
+ stopHere = isDalvikRegisterClobbered(thisLIR, checkLIR);
+ }
+
+ /*
+ * Stop at an earlier Dalvik load if the offset of checkLIR
+ * is not less than thisLIR
+ *
+ * Experiments show that doing
+ *
+ * ldr r1, [r5, #16]
+ * ldr r0, [r5, #20]
+ *
+ * is much faster than
+ *
+ * ldr r0, [r5, #20]
+ * ldr r1, [r5, #16]
+ */
+ if (isDalvikLoad(checkLIR)) {
+ int dRegId2 =
+ DECODE_ALIAS_INFO_REG(checkLIR->aliasInfo);
+ if (dRegId2 <= dRegId) {
+ stopHere = true;
+ }
+ }
+
+ /* Found a new place to put the load - move it here */
+ if (stopHere == true) {
+ DEBUG_OPT(dumpDependentInsnPair(thisLIR, checkLIR,
+ "HOIST LOAD"));
+ /* The store can be hoisted for at least one cycle */
+ if (hoistDistance != 0) {
+ ArmLIR *newLoadLIR =
+ dvmCompilerNew(sizeof(ArmLIR), true);
+ *newLoadLIR = *thisLIR;
+ newLoadLIR->age = cUnit->optRound;
+ /*
+ * Insertion is guaranteed to succeed since checkLIR
+ * is never the first LIR on the list
+ */
+ dvmCompilerInsertLIRAfter((LIR *) checkLIR,
+ (LIR *) newLoadLIR);
+ thisLIR->isNop = true;
+ }
+ break;
+ }
+
+ /*
+ * Saw a real instruction that hosting the load is
+ * beneficial
+ */
+ if (!isPseudoOpCode(checkLIR->opCode)) {
+ hoistDistance++;
+ }
+ }
+ }
+ }
+ }
+}
+
void dvmCompilerApplyLocalOptimizations(CompilationUnit *cUnit, LIR *headLIR,
LIR *tailLIR)
{
- applyLoadStoreElimination(cUnit,
- (ArmLIR *) headLIR,
- (ArmLIR *) tailLIR);
+ if (!(gDvmJit.disableOpt & (1 << kLoadStoreElimination))) {
+ applyLoadStoreElimination(cUnit, (ArmLIR *) headLIR,
+ (ArmLIR *) tailLIR);
+ }
+ if (!(gDvmJit.disableOpt & (1 << kLoadHoisting))) {
+ applyLoadHoisting(cUnit, (ArmLIR *) headLIR, (ArmLIR *) tailLIR);
+ }
}
diff --git a/vm/compiler/codegen/arm/Thumb2Util.c b/vm/compiler/codegen/arm/Thumb2Util.c
index 3a9f1de..dfbb030 100644
--- a/vm/compiler/codegen/arm/Thumb2Util.c
+++ b/vm/compiler/codegen/arm/Thumb2Util.c
@@ -16,46 +16,85 @@
/*
* This file contains codegen for the Thumb ISA and is intended to be
- * includes by:and support common to all supported
+ * includes by:
*
* Codegen-$(TARGET_ARCH_VARIANT).c
*
*/
#include "Codegen.h"
+/* Forward decls */
+static ArmLIR *genNullCheck(CompilationUnit *cUnit, int vReg, int mReg,
+ int dOffset, ArmLIR *pcrLabel);
+static ArmLIR *loadValueAddress(CompilationUnit *cUnit, int vSrc, int rDest);
+static ArmLIR *loadValue(CompilationUnit *cUnit, int vSrc, int rDest);
+static ArmLIR *loadWordDisp(CompilationUnit *cUnit, int rBase,
+ int displacement, int rDest);
+static ArmLIR *storeWordDisp(CompilationUnit *cUnit, int rBase,
+ int displacement, int rSrc, int rScratch);
+static ArmLIR *storeValue(CompilationUnit *cUnit, int rSrc, int vDest,
+ int rScratch);
+static ArmLIR *genConditionalBranch(CompilationUnit *cUnit,
+ ArmConditionCode cond,
+ ArmLIR *target);
+static ArmLIR *genUnconditionalBranch(CompilationUnit *cUnit, ArmLIR *target);
+static ArmLIR *loadValuePair(CompilationUnit *cUnit, int vSrc, int rDestLo,
+ int rDestHi);
+static ArmLIR *storeValuePair(CompilationUnit *cUnit, int rSrcLo, int rSrcHi,
+ int vDest, int rScratch);
+static ArmLIR *genBoundsCheck(CompilationUnit *cUnit, int rIndex,
+ int rBound, int dOffset, ArmLIR *pcrLabel);
+static ArmLIR *genRegCopy(CompilationUnit *cUnit, int rDest, int rSrc);
+static int inlinedTarget(MIR *mir);
+
/* Routines which must be supplied here */
-static void loadConstant(CompilationUnit *cUnit, int rDest, int value);
-static void genExportPC(CompilationUnit *cUnit, MIR *mir, int rDPC, int rAddr);
-static void genConditionalBranch(CompilationUnit *cUnit,
- ArmConditionCode cond,
- ArmLIR *target);
-static ArmLIR *genUnconditionalBranch(CompilationUnit *cUnit, ArmLIR *target);
-static void loadValuePair(CompilationUnit *cUnit, int vSrc, int rDestLo,
- int rDestHi);
-static void storeValuePair(CompilationUnit *cUnit, int rSrcLo, int rSrcHi,
- int vDest, int rScratch);
-static void loadValueAddress(CompilationUnit *cUnit, int vSrc, int vDest);
-static void loadValue(CompilationUnit *cUnit, int vSrc, int rDest);
-static void loadWordDisp(CompilationUnit *cUnit, int rBase, int displacement,
- int rDest);
-static void storeValue(CompilationUnit *cUnit, int rSrc, int vDest,
- int rScratch);
+static ArmLIR *loadConstant(CompilationUnit *cUnit, int rDest, int value);
+static ArmLIR *genExportPC(CompilationUnit *cUnit, MIR *mir, int rDPC,
+ int rAddr);
+static ArmLIR *loadBaseDisp(CompilationUnit *cUnit, MIR *mir, int rBase,
+ int displacement, int rDest, OpSize size,
+ bool nullCheck, int vReg);
+static ArmLIR *storeBaseDisp(CompilationUnit *cUnit, int rBase,
+ int displacement, int rSrc, OpSize size,
+ int rScratch);
static inline ArmLIR *genRegImmCheck(CompilationUnit *cUnit,
- ArmConditionCode cond, int reg,
- int checkValue, int dOffset,
- ArmLIR *pcrLabel);
+ ArmConditionCode cond, int reg,
+ int checkValue, int dOffset,
+ ArmLIR *pcrLabel);
ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc);
+static ArmLIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask);
+static ArmLIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask);
-/*****************************************************************************/
+static ArmLIR *opNone(CompilationUnit *cUnit, OpKind op);
+static ArmLIR *opImm(CompilationUnit *cUnit, OpKind op, int value);
+static ArmLIR *opCondBranch(CompilationUnit *cUnit, ArmConditionCode cc);
+static ArmLIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc);
+static ArmLIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
+ int rSrc2);
+static ArmLIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
+ int value, int rScratch);
+static ArmLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
+ int rSrc1, int value, int rScratch);
+static ArmLIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest,
+ int rSrc1, int rSrc2);
+static ArmLIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase,
+ int rIndex, int rDest, int scale, OpSize size);
+static void genCmpLong(CompilationUnit *cUnit, MIR *mir, int vDest, int vSrc1,
+ int vSrc2);
+
+static bool genInlinedStringLength(CompilationUnit *cUnit, MIR *mir);
+static bool genInlinedStringCharAt(CompilationUnit *cUnit, MIR *mir);
+static bool genInlinedAbsInt(CompilationUnit *cUnit, MIR *mir);
+static bool genInlinedAbsFloat(CompilationUnit *cUnit, MIR *mir);
+static bool genInlinedAbsDouble(CompilationUnit *cUnit, MIR *mir);
+static bool genInlinedMinMaxInt(CompilationUnit *cUnit, MIR *mir, bool isMin);
+static bool genInlinedAbsLong(CompilationUnit *cUnit, MIR *mir);
/*
* Support for register allocation
*/
-/* non-existent register */
-#define vNone (-1)
-
/* get the next register in r0..r3 in a round-robin fashion */
#define NEXT_REG(reg) ((reg + 1) & 3)
/*
@@ -67,11 +106,16 @@
static inline void resetRegisterScoreboard(CompilationUnit *cUnit)
{
RegisterScoreboard *registerScoreboard = &cUnit->registerScoreboard;
+ int i;
dvmClearAllBits(registerScoreboard->nullCheckedRegs);
registerScoreboard->liveDalvikReg = vNone;
registerScoreboard->nativeReg = vNone;
registerScoreboard->nativeRegHi = vNone;
+ for (i = 0; i < 32; i++) {
+ registerScoreboard->fp[i] = vNone;
+ }
+ registerScoreboard->nextFP = 0;
}
/* Kill the corresponding bit in the null-checked register list */
@@ -128,12 +172,50 @@
} else {
return (registerScoreboard->nativeReg + 1) & 3;
}
-
}
-/*****************************************************************************/
+/*
+ * Generate a Thumb2 IT instruction, which can nullify up to
+ * four subsequent instructions based on a condition and its
+ * inverse. The condition applies to the first instruction, which
+ * is executed if the condition is met. The string "guide" consists
+ * of 0 to 3 chars, and applies to the 2nd through 4th instruction.
+ * A "T" means the instruction is executed if the condition is
+ * met, and an "E" means the instruction is executed if the condition
+ * is not met.
+ */
+static ArmLIR *genIT(CompilationUnit *cUnit, ArmConditionCode code,
+ char *guide)
+{
+ int mask;
+ int condBit = code & 1;
+ int altBit = condBit ^ 1;
+ int mask3 = 0;
+ int mask2 = 0;
+ int mask1 = 0;
-ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
+ //Note: case fallthroughs intentional
+ switch(strlen(guide)) {
+ case 3:
+ mask1 = (guide[2] == 'T') ? condBit : altBit;
+ case 2:
+ mask2 = (guide[1] == 'T') ? condBit : altBit;
+ case 1:
+ mask3 = (guide[0] == 'T') ? condBit : altBit;
+ break;
+ case 0:
+ break;
+ default:
+ assert(0);
+ dvmAbort();
+ }
+ mask = (mask3 << 3) | (mask2 << 2) | (mask1 << 1) |
+ (1 << (3 - strlen(guide)));
+ return newLIR2(cUnit, THUMB2_IT, code, mask);
+}
+
+
+static ArmLIR *fpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
{
ArmLIR* res = dvmCompilerNew(sizeof(ArmLIR), true);
res->operands[0] = rDest;
@@ -141,22 +223,43 @@
if (rDest == rSrc) {
res->isNop = true;
} else {
- if (LOWREG(rDest) && LOWREG(rSrc)) {
- res->opCode = THUMB_MOV_RR;
- } else if (FPREG(rDest) && FPREG(rSrc)) {
- if (DOUBLEREG(rDest)) {
- assert(DOUBLEREG(rSrc));
- res->opCode = THUMB2_VMOVD;
- } else {
- assert(SINGLEREG(rSrc));
- res->opCode = THUMB2_VMOVS;
- }
+ // TODO: support copy between FP and gen regs
+ if (DOUBLEREG(rDest)) {
+ assert(DOUBLEREG(rSrc));
+ res->opCode = THUMB2_VMOVD;
} else {
- // TODO: support copy between FP and gen regs.
- assert(!FPREG(rDest));
- assert(!FPREG(rSrc));
- res->opCode = THUMB2_MOV_RR;
+ assert(SINGLEREG(rSrc));
+ res->opCode = THUMB2_VMOVS;
}
+ res->operands[0] = rDest;
+ res->operands[1] = rSrc;
+ }
+ setupResourceMasks(res);
+ return res;
+}
+
+ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
+{
+ ArmLIR* res;
+ ArmOpCode opCode;
+ if (FPREG(rDest) || FPREG(rSrc))
+ return fpRegCopy(cUnit, rDest, rSrc);
+ res = dvmCompilerNew(sizeof(ArmLIR), true);
+ if (LOWREG(rDest) && LOWREG(rSrc))
+ opCode = THUMB_MOV_RR;
+ else if (!LOWREG(rDest) && !LOWREG(rSrc))
+ opCode = THUMB_MOV_RR_H2H;
+ else if (LOWREG(rDest))
+ opCode = THUMB_MOV_RR_H2L;
+ else
+ opCode = THUMB_MOV_RR_L2H;
+
+ res->operands[0] = rDest;
+ res->operands[1] = rSrc;
+ res->opCode = opCode;
+ setupResourceMasks(res);
+ if (rDest == rSrc) {
+ res->isNop = true;
}
return res;
}
@@ -181,7 +284,7 @@
}
/*
- * Determine whether value can be encoded as a Thumb modified
+ * Determine whether value can be encoded as a Thumb2 modified
* immediate. If not, return -1. If so, return i:imm3:a:bcdefgh form.
*/
static int modifiedImmediate(u4 value)
@@ -218,28 +321,29 @@
* Load a immediate using a shortcut if possible; otherwise
* grab from the per-translation literal pool
*/
-static void loadConstant(CompilationUnit *cUnit, int rDest, int value)
+static ArmLIR *loadConstant(CompilationUnit *cUnit, int rDest, int value)
{
+ ArmLIR *res;
int modImm;
/* See if the value can be constructed cheaply */
- if ((value & 0xff) == value) {
- newLIR2(cUnit, THUMB_MOV_IMM, rDest, value);
- return;
- } else if ((value & 0xFFFFFF00) == 0xFFFFFF00) {
- newLIR2(cUnit, THUMB_MOV_IMM, rDest, ~value);
- newLIR2(cUnit, THUMB_MVN, rDest, rDest);
- return;
+ if ((value >= 0) && (value <= 255)) {
+ return newLIR2(cUnit, THUMB_MOV_IMM, rDest, value);
}
/* Check Modified immediate special cases */
modImm = modifiedImmediate(value);
if (modImm >= 0) {
- newLIR2(cUnit, THUMB2_MOV_IMM_SHIFT, rDest, modImm);
- return;
+ res = newLIR2(cUnit, THUMB2_MOV_IMM_SHIFT, rDest, modImm);
+ return res;
+ }
+ modImm = modifiedImmediate(~value);
+ if (modImm >= 0) {
+ res = newLIR2(cUnit, THUMB2_MVN_IMM_SHIFT, rDest, modImm);
+ return res;
}
/* 16-bit immediate? */
if ((value & 0xffff) == value) {
- newLIR2(cUnit, THUMB2_MOV_IMM16, rDest, value);
- return;
+ res = newLIR2(cUnit, THUMB2_MOV_IMM16, rDest, value);
+ return res;
}
/* No shortcut - go ahead and use literal pool */
ArmLIR *dataTarget = scanLiteralPool(cUnit, value, 255);
@@ -250,6 +354,8 @@
loadPcRel->opCode = THUMB_LDR_PC_REL;
loadPcRel->generic.target = (LIR *) dataTarget;
loadPcRel->operands[0] = rDest;
+ setupResourceMasks(loadPcRel);
+ res = loadPcRel;
dvmCompilerAppendLIR(cUnit, (LIR *) loadPcRel);
/*
@@ -259,210 +365,359 @@
if (dataTarget->operands[0] != value) {
newLIR2(cUnit, THUMB_ADD_RI8, rDest, value - dataTarget->operands[0]);
}
+ return res;
}
/* Export the Dalvik PC assicated with an instruction to the StackSave area */
-static void genExportPC(CompilationUnit *cUnit, MIR *mir, int rDPC, int rAddr)
+static ArmLIR *genExportPC(CompilationUnit *cUnit, MIR *mir, int rDPC,
+ int rAddr)
{
+ ArmLIR *res;
int offset = offsetof(StackSaveArea, xtra.currentPc);
- loadConstant(cUnit, rDPC, (int) (cUnit->method->insns + mir->offset));
+ res = loadConstant(cUnit, rDPC, (int) (cUnit->method->insns + mir->offset));
newLIR3(cUnit, THUMB2_STR_RRI8_PREDEC, rDPC, rFP,
sizeof(StackSaveArea) - offset);
+ return res;
}
-/* Generate conditional branch instructions */
-static void genConditionalBranch(CompilationUnit *cUnit,
- ArmConditionCode cond,
- ArmLIR *target)
+/* Load value from base + scaled index. Note: index reg killed */
+static ArmLIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase,
+ int rIndex, int rDest, int scale, OpSize size)
{
- ArmLIR *branch = newLIR2(cUnit, THUMB_B_COND, 0, cond);
- branch->generic.target = (LIR *) target;
+ bool allLowRegs = LOWREG(rBase) && LOWREG(rIndex) && LOWREG(rDest);
+ ArmOpCode opCode = THUMB_BKPT;
+ bool thumbForm = (allLowRegs && (scale == 0));
+ switch (size) {
+ case WORD:
+ opCode = (thumbForm) ? THUMB_LDR_RRR : THUMB2_LDR_RRR;
+ break;
+ case UNSIGNED_HALF:
+ opCode = (thumbForm) ? THUMB_LDRH_RRR : THUMB2_LDRH_RRR;
+ break;
+ case SIGNED_HALF:
+ opCode = (thumbForm) ? THUMB_LDRSH_RRR : THUMB2_LDRSH_RRR;
+ break;
+ case UNSIGNED_BYTE:
+ opCode = (thumbForm) ? THUMB_LDRB_RRR : THUMB2_LDRB_RRR;
+ break;
+ case SIGNED_BYTE:
+ opCode = (thumbForm) ? THUMB_LDRSB_RRR : THUMB2_LDRSB_RRR;
+ break;
+ default:
+ assert(0);
+ }
+ if (thumbForm)
+ return newLIR3(cUnit, opCode, rDest, rBase, rIndex);
+ else
+ return newLIR4(cUnit, opCode, rDest, rBase, rIndex, scale);
}
-/* Generate unconditional branch instructions */
-static ArmLIR *genUnconditionalBranch(CompilationUnit *cUnit, ArmLIR *target)
+/* store value base base + scaled index. Note: index reg killed */
+static ArmLIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase,
+ int rIndex, int rSrc, int scale, OpSize size)
{
- ArmLIR *branch = newLIR0(cUnit, THUMB_B_UNCOND);
- branch->generic.target = (LIR *) target;
- return branch;
+ bool allLowRegs = LOWREG(rBase) && LOWREG(rIndex) && LOWREG(rSrc);
+ ArmOpCode opCode = THUMB_BKPT;
+ bool thumbForm = (allLowRegs && (scale == 0));
+ switch (size) {
+ case WORD:
+ opCode = (thumbForm) ? THUMB_STR_RRR : THUMB2_STR_RRR;
+ break;
+ case UNSIGNED_HALF:
+ case SIGNED_HALF:
+ opCode = (thumbForm) ? THUMB_STRH_RRR : THUMB2_STRH_RRR;
+ break;
+ case UNSIGNED_BYTE:
+ case SIGNED_BYTE:
+ opCode = (thumbForm) ? THUMB_STRB_RRR : THUMB2_STRB_RRR;
+ break;
+ default:
+ assert(0);
+ }
+ if (thumbForm)
+ return newLIR3(cUnit, opCode, rSrc, rBase, rIndex);
+ else
+ return newLIR4(cUnit, opCode, rSrc, rBase, rIndex, scale);
}
/*
- * Load a pair of values of rFP[src..src+1] and store them into rDestLo and
- * rDestHi
+ * Load a float from a Dalvik register. Note: using fixed r7 here
+ * when operation is out of range. Revisit this when registor allocation
+ * strategy changes.
*/
-static void loadValuePair(CompilationUnit *cUnit, int vSrc, int rDestLo,
- int rDestHi)
+static ArmLIR *fpVarAccess(CompilationUnit *cUnit, int vSrcDest,
+ int rSrcDest, ArmOpCode opCode)
{
- bool allLowRegs = (LOWREG(rDestLo) && LOWREG(rDestHi));
-
- /* Use reg + imm5*4 to load the values if possible */
- if (allLowRegs && vSrc <= 30) {
- newLIR3(cUnit, THUMB_LDR_RRI5, rDestLo, rFP, vSrc);
- newLIR3(cUnit, THUMB_LDR_RRI5, rDestHi, rFP, vSrc+1);
+ ArmLIR *res;
+ if (vSrcDest > 255) {
+ opRegRegImm(cUnit, OP_ADD, r7, rFP, vSrcDest * 4, rNone);
+ res = newLIR3(cUnit, opCode, rSrcDest, r7, 0);
} else {
- assert(rDestLo < rDestHi);
- loadValueAddress(cUnit, vSrc, rDestLo);
- if (allLowRegs) {
- newLIR2(cUnit, THUMB_LDMIA, rDestLo, (1<<rDestLo) | (1<<(rDestHi)));
- } else {
- assert(0); // Unimp - need Thumb2 ldmia
+ res = newLIR3(cUnit, opCode, rSrcDest, rFP, vSrcDest);
+ }
+ return res;
+}
+
+static int nextFPReg(CompilationUnit *cUnit, int dalvikReg, bool isDouble)
+{
+ RegisterScoreboard *registerScoreboard = &cUnit->registerScoreboard;
+ int reg;
+
+ if (isDouble) {
+ reg = ((registerScoreboard->nextFP + 1) & ~1) % 32;
+ registerScoreboard->nextFP = reg + 2;
+ registerScoreboard->nextFP %= 32;
+ registerScoreboard->fp[reg] = dalvikReg;
+ return dr0 + reg;
+ }
+ else {
+ reg = registerScoreboard->nextFP++;
+ registerScoreboard->nextFP %= 32;
+ registerScoreboard->fp[reg] = dalvikReg;
+ return fr0 + reg;
+ }
+}
+
+/*
+ * Select a SFP register for the dalvikReg
+ */
+static int selectSFPReg(CompilationUnit *cUnit, int dalvikReg)
+{
+ RegisterScoreboard *registerScoreboard = &cUnit->registerScoreboard;
+ int i;
+
+ if (dalvikReg == vNone) {
+ return nextFPReg(cUnit, dalvikReg, false);;
+ }
+
+ for (i = 0; i < 32; i++) {
+ if (registerScoreboard->fp[i] == dalvikReg) {
+ return fr0 + i;
}
}
+ return nextFPReg(cUnit, dalvikReg, false);;
}
/*
- * Store a pair of values of rSrc and rSrc+1 and store them into vDest and
- * vDest+1
+ * Select a DFP register for the dalvikReg
*/
-static void storeValuePair(CompilationUnit *cUnit, int rSrcLo, int rSrcHi,
- int vDest, int rScratch)
+static int selectDFPReg(CompilationUnit *cUnit, int dalvikReg)
{
- bool allLowRegs = (LOWREG(rSrcLo) && LOWREG(rSrcHi));
- killNullCheckedRegister(cUnit, vDest);
- killNullCheckedRegister(cUnit, vDest+1);
- updateLiveRegisterPair(cUnit, vDest, rSrcLo, rSrcHi);
+ RegisterScoreboard *registerScoreboard = &cUnit->registerScoreboard;
+ int i;
- /* Use reg + imm5*4 to store the values if possible */
- if (allLowRegs && vDest <= 30) {
- newLIR3(cUnit, THUMB_STR_RRI5, rSrcLo, rFP, vDest);
- newLIR3(cUnit, THUMB_STR_RRI5, rSrcHi, rFP, vDest+1);
- } else {
- assert(rSrcLo < rSrcHi);
- loadValueAddress(cUnit, vDest, rScratch);
- if (allLowRegs) {
- newLIR2(cUnit, THUMB_STMIA, rScratch,
- (1<<rSrcLo) | (1 << (rSrcHi)));
- } else {
- assert(0); // Unimp - need Thumb2 stmia
+ if (dalvikReg == vNone) {
+ return nextFPReg(cUnit, dalvikReg, true);;
+ }
+
+ for (i = 0; i < 32; i += 2) {
+ if (registerScoreboard->fp[i] == dalvikReg) {
+ return dr0 + i;
}
}
+ return nextFPReg(cUnit, dalvikReg, true);
}
-static void addRegisterRegister(CompilationUnit *cUnit, int rDest,
- int rSrc1, int rSrc2)
+static ArmLIR *loadFloat(CompilationUnit *cUnit, int vSrc, int rDest)
{
- if (!LOWREG(rDest) || !LOWREG(rSrc1) || !LOWREG(rSrc2)) {
- assert(0); // Unimp
- //newLIR3(cUnit, THUMB2_ADD_RRR, rDest, rFP, rDest);
- } else {
- newLIR3(cUnit, THUMB_ADD_RRR, rDest, rFP, rDest);
- }
-}
-
-/* Add in immediate to a register. */
-static void addRegisterImmediate(CompilationUnit *cUnit, int rDest, int rSrc,
- int value)
-{
-// TODO: check for modified immediate form
- if (LOWREG(rDest) && LOWREG(rSrc) && (value <= 7)) {
- newLIR3(cUnit, THUMB_ADD_RRI3, rDest, rSrc, value);
- } else if (LOWREG(rDest) && (rDest == rSrc) && ((value & 0xff) == 0xff)) {
- newLIR2(cUnit, THUMB_ADD_RI8, rDest, value);
- } else if (value <= 4095) {
- newLIR3(cUnit, THUMB2_ADD_RRI12, rDest, rSrc, value);
- } else {
- loadConstant(cUnit, rDest, value);
- addRegisterRegister(cUnit, rDest, rDest, rFP);
- }
-}
-
-/* Load the address of a Dalvik register on the frame */
-static void loadValueAddress(CompilationUnit *cUnit, int vSrc, int rDest)
-{
- addRegisterImmediate(cUnit, rDest, rFP, vSrc*4);
-}
-
-/*
- * FIXME: We need a general register temp for all of these coprocessor
- * operations in case we can't reach in 1 shot. Might just want to
- * designate a hot temp that all codegen routines could use in their
- * scope. Alternately, callers will need to allocate a temp and
- * pass it in to each of these.
- */
-
-/* Load a float from a Dalvik register */
-static void loadFloat(CompilationUnit *cUnit, int vSrc, int rDest)
-{
- assert(vSrc <= 255); // FIXME - temp limit to 1st 256
assert(SINGLEREG(rDest));
- newLIR3(cUnit, THUMB2_VLDRS, rDest, rFP, vSrc);
+ ArmLIR *lir = fpVarAccess(cUnit, vSrc, rDest, THUMB2_VLDRS);
+ annotateDalvikRegAccess(lir, vSrc, true /* isLoad */);
+ return lir;
}
/* Store a float to a Dalvik register */
-static void storeFloat(CompilationUnit *cUnit, int rSrc, int vDest,
- int rScratch)
+static ArmLIR *storeFloat(CompilationUnit *cUnit, int rSrc, int vDest)
{
- assert(vSrc <= 255); // FIXME - temp limit to 1st 256
+ RegisterScoreboard *registerScoreboard = &cUnit->registerScoreboard;
+
assert(SINGLEREG(rSrc));
- newLIR3(cUnit, THUMB2_VSTRS, rSrc, rFP, vDest);
+ registerScoreboard->fp[rSrc % 32] = vDest;
+
+ ArmLIR *lir = fpVarAccess(cUnit, vDest, rSrc, THUMB2_VSTRS);
+ annotateDalvikRegAccess(lir, vDest, false /* isLoad */);
+ return lir;
}
/* Load a double from a Dalvik register */
-static void loadDouble(CompilationUnit *cUnit, int vSrc, int rDest)
+static ArmLIR *loadDouble(CompilationUnit *cUnit, int vSrc, int rDest)
{
- assert(vSrc <= 255); // FIXME - temp limit to 1st 256
assert(DOUBLEREG(rDest));
- newLIR3(cUnit, THUMB2_VLDRD, rDest, rFP, vSrc);
+ ArmLIR *lir = fpVarAccess(cUnit, vSrc, rDest, THUMB2_VLDRD);
+ annotateDalvikRegAccess(lir, vSrc, true /* isLoad */);
+ return lir;
}
/* Store a double to a Dalvik register */
-static void storeDouble(CompilationUnit *cUnit, int rSrc, int vDest,
- int rScratch)
+static ArmLIR *storeDouble(CompilationUnit *cUnit, int rSrc, int vDest)
{
- assert(vSrc <= 255); // FIXME - temp limit to 1st 256
+ RegisterScoreboard *registerScoreboard = &cUnit->registerScoreboard;
+
assert(DOUBLEREG(rSrc));
- newLIR3(cUnit, THUMB2_VSTRD, rSrc, rFP, vDest);
+ registerScoreboard->fp[rSrc % 32] = vDest;
+
+ ArmLIR *lir = fpVarAccess(cUnit, vDest, rSrc, THUMB2_VSTRD);
+ annotateDalvikRegAccess(lir, vDest, false /* isLoad */);
+ return lir;
}
-
-/* Load a single value from rFP[src] and store them into rDest */
-static void loadValue(CompilationUnit *cUnit, int vSrc, int rDest)
+/*
+ * Load value from base + displacement. Optionally perform null check
+ * on base (which must have an associated vReg and MIR). If not
+ * performing null check, incoming MIR can be null. Note: base and
+ * dest must not be the same if there is any chance that the long
+ * form must be used.
+ * TODO: revisit, perhaps use hot temp reg in (base == dest) case.
+ */
+static ArmLIR *loadBaseDisp(CompilationUnit *cUnit, MIR *mir, int rBase,
+ int displacement, int rDest, OpSize size,
+ bool nullCheck, int vReg)
{
- loadWordDisp(cUnit, rFP, vSrc * 4, rDest);
-}
-
-/* Load a word at base + displacement. Displacement must be word multiple */
-static void loadWordDisp(CompilationUnit *cUnit, int rBase, int displacement,
- int rDest)
-{
+ ArmLIR *first = NULL;
+ ArmLIR *res, *load;
+ ArmOpCode opCode = THUMB_BKPT;
+ bool shortForm = false;
+ bool thumb2Form = (displacement < 4092 && displacement >= 0);
+ int shortMax = 128;
bool allLowRegs = (LOWREG(rBase) && LOWREG(rDest));
- assert((displacement & 0x3) == 0);
- /* Can it fit in a RRI5? */
- if (allLowRegs && displacement < 128) {
- newLIR3(cUnit, THUMB_LDR_RRI5, rDest, rBase, displacement >> 2);
- } else if (displacement < 4092) {
- newLIR3(cUnit, THUMB2_LDR_RRI12, rDest, rFP, displacement);
- } else {
- loadConstant(cUnit, rDest, displacement);
- if (allLowRegs) {
- newLIR3(cUnit, THUMB_LDR_RRR, rDest, rBase, rDest);
- } else {
- assert(0); // Unimp - need Thumb2 ldr_rrr
- }
+ int encodedDisp = displacement;
+
+ switch (size) {
+ case WORD:
+ if (LOWREG(rDest) && (rBase == rpc) &&
+ (displacement <= 1020) && (displacement >= 0)) {
+ shortForm = true;
+ encodedDisp >>= 2;
+ opCode = THUMB_LDR_PC_REL;
+ } else if (LOWREG(rDest) && (rBase == r13) &&
+ (displacement <= 1020) && (displacement >= 0)) {
+ shortForm = true;
+ encodedDisp >>= 2;
+ opCode = THUMB_LDR_SP_REL;
+ } else if (allLowRegs && displacement < 128 && displacement >= 0) {
+ assert((displacement & 0x3) == 0);
+ shortForm = true;
+ encodedDisp >>= 2;
+ opCode = THUMB_LDR_RRI5;
+ } else if (thumb2Form) {
+ shortForm = true;
+ opCode = THUMB2_LDR_RRI12;
+ }
+ break;
+ case UNSIGNED_HALF:
+ if (allLowRegs && displacement < 64 && displacement >= 0) {
+ assert((displacement & 0x1) == 0);
+ shortForm = true;
+ encodedDisp >>= 1;
+ opCode = THUMB_LDRH_RRI5;
+ } else if (displacement < 4092 && displacement >= 0) {
+ shortForm = true;
+ opCode = THUMB2_LDRH_RRI12;
+ }
+ break;
+ case SIGNED_HALF:
+ if (thumb2Form) {
+ shortForm = true;
+ opCode = THUMB2_LDRSH_RRI12;
+ }
+ break;
+ case UNSIGNED_BYTE:
+ if (allLowRegs && displacement < 32 && displacement >= 0) {
+ shortForm = true;
+ opCode = THUMB_LDRB_RRI5;
+ } else if (thumb2Form) {
+ shortForm = true;
+ opCode = THUMB2_LDRB_RRI12;
+ }
+ break;
+ case SIGNED_BYTE:
+ if (thumb2Form) {
+ shortForm = true;
+ opCode = THUMB2_LDRSB_RRI12;
+ }
+ break;
+ default:
+ assert(0);
}
+ if (nullCheck)
+ first = genNullCheck(cUnit, vReg, rBase, mir->offset, NULL);
+ if (shortForm) {
+ load = res = newLIR3(cUnit, opCode, rDest, rBase, encodedDisp);
+ } else {
+ assert(rBase != rDest);
+ res = loadConstant(cUnit, rDest, encodedDisp);
+ load = loadBaseIndexed(cUnit, rBase, rDest, rDest, 0, size);
+ }
+
+ if (rBase == rFP) {
+ annotateDalvikRegAccess(load, displacement >> 2, true /* isLoad */);
+ }
+ return (first) ? first : res;
}
-/* Store a value from rSrc to vDest */
-static void storeValue(CompilationUnit *cUnit, int rSrc, int vDest,
- int rScratch)
+static ArmLIR *storeBaseDisp(CompilationUnit *cUnit, int rBase,
+ int displacement, int rSrc, OpSize size,
+ int rScratch)
{
- killNullCheckedRegister(cUnit, vDest);
- updateLiveRegister(cUnit, vDest, rSrc);
+ ArmLIR *res, *store;
+ ArmOpCode opCode = THUMB_BKPT;
+ bool shortForm = false;
+ bool thumb2Form = (displacement < 4092 && displacement >= 0);
+ int shortMax = 128;
+ bool allLowRegs = (LOWREG(rBase) && LOWREG(rSrc));
+ int encodedDisp = displacement;
- /* Use reg + imm5*4 to store the value if possible */
- if (LOWREG(rSrc) && vDest <= 31) {
- newLIR3(cUnit, THUMB_STR_RRI5, rSrc, rFP, vDest);
- } else if (vDest <= 1023) {
- newLIR3(cUnit, THUMB2_STR_RRI12, rSrc, rFP, vDest*4);
- } else {
- loadConstant(cUnit, rScratch, vDest*4);
- if (LOWREG(rSrc)) {
- newLIR3(cUnit, THUMB_STR_RRR, rSrc, rFP, rScratch);
- } else {
- assert(0); // Unimp: Need generic str_rrr routine
- }
+ if (rScratch != -1)
+ allLowRegs &= LOWREG(rScratch);
+ switch (size) {
+ case WORD:
+ if (allLowRegs && displacement < 128 && displacement >= 0) {
+ assert((displacement & 0x3) == 0);
+ shortForm = true;
+ encodedDisp >>= 2;
+ opCode = THUMB_STR_RRI5;
+ } else if (thumb2Form) {
+ shortForm = true;
+ opCode = THUMB2_STR_RRI12;
+ }
+ break;
+ case UNSIGNED_HALF:
+ case SIGNED_HALF:
+ if (displacement < 64 && displacement >= 0) {
+ assert((displacement & 0x1) == 0);
+ shortForm = true;
+ encodedDisp >>= 1;
+ opCode = THUMB_STRH_RRI5;
+ } else if (thumb2Form) {
+ shortForm = true;
+ opCode = THUMB2_STRH_RRI12;
+ }
+ break;
+ case UNSIGNED_BYTE:
+ case SIGNED_BYTE:
+ if (displacement < 32 && displacement >= 0) {
+ shortForm = true;
+ opCode = THUMB_STRB_RRI5;
+ } else if (thumb2Form) {
+ shortForm = true;
+ opCode = THUMB2_STRH_RRI12;
+ }
+ break;
+ default:
+ assert(0);
}
+ if (shortForm) {
+ store = res = newLIR3(cUnit, opCode, rSrc, rBase, encodedDisp);
+ } else {
+ assert(rScratch != -1);
+ res = loadConstant(cUnit, rScratch, encodedDisp);
+ store = storeBaseIndexed(cUnit, rBase, rScratch, rSrc, 0, size);
+ }
+
+ if (rBase == rFP) {
+ annotateDalvikRegAccess(store, displacement >> 2, false /* isLoad */);
+ }
+ return res;
}
/*
@@ -475,14 +730,658 @@
ArmLIR *pcrLabel)
{
ArmLIR *branch;
- if ((LOWREG(reg)) && (checkValue == 0) &&
+ int modImm;
+ /*
+ * TODO: re-enable usage of THUMB2_CBZ & THUMB2_CBNZ once assembler is
+ * enhanced to allow us to replace code patterns when instructions don't
+ * reach. Currently, CB[N]Z is causing too many assembler aborts.
+ * What we want to do is emit the short forms, and then replace them with
+ * longer versions when needed.
+ */
+ if (0 && (LOWREG(reg)) && (checkValue == 0) &&
((cond == ARM_COND_EQ) || (cond == ARM_COND_NE))) {
branch = newLIR2(cUnit,
(cond == ARM_COND_EQ) ? THUMB2_CBZ : THUMB2_CBNZ,
reg, 0);
} else {
- newLIR2(cUnit, THUMB_CMP_RI8, reg, checkValue);
+ modImm = modifiedImmediate(checkValue);
+ if ((checkValue & 0xff) == checkValue) {
+ newLIR2(cUnit, THUMB_CMP_RI8, reg, checkValue);
+ } else if (modImm >= 0) {
+ newLIR2(cUnit, THUMB2_CMP_RI8, reg, modImm);
+ } else {
+ /* Note: direct use of hot temp r7 here. Revisit. */
+ loadConstant(cUnit, r7, checkValue);
+ newLIR2(cUnit, THUMB_CMP_RR, reg, r7);
+ }
branch = newLIR2(cUnit, THUMB_B_COND, 0, cond);
}
return genCheckCommon(cUnit, dOffset, branch, pcrLabel);
}
+
+static ArmLIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask)
+{
+ ArmLIR *res;
+ if (LOWREG(rBase) && ((rMask & 0xff)==rMask)) {
+ res = newLIR2(cUnit, THUMB_LDMIA, rBase, rMask);
+ } else {
+ res = newLIR2(cUnit, THUMB2_LDMIA, rBase, rMask);
+ }
+ return res;
+}
+
+static ArmLIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask)
+{
+ ArmLIR *res;
+ if (LOWREG(rBase) && ((rMask & 0xff)==rMask)) {
+ res = newLIR2(cUnit, THUMB_STMIA, rBase, rMask);
+ } else {
+ res = newLIR2(cUnit, THUMB2_STMIA, rBase, rMask);
+ }
+ return res;
+}
+
+static ArmLIR *opNone(CompilationUnit *cUnit, OpKind op)
+{
+ ArmOpCode opCode = THUMB_BKPT;
+ switch (op) {
+ case OP_UNCOND_BR:
+ opCode = THUMB_B_UNCOND;
+ break;
+ default:
+ assert(0);
+ }
+ return newLIR0(cUnit, opCode);
+}
+
+static ArmLIR *opCondBranch(CompilationUnit *cUnit, ArmConditionCode cc)
+{
+ return newLIR2(cUnit, THUMB_B_COND, 0 /* offset to be patched */, cc);
+}
+
+static ArmLIR *opImm(CompilationUnit *cUnit, OpKind op, int value)
+{
+ ArmOpCode opCode = THUMB_BKPT;
+ switch (op) {
+ case OP_PUSH:
+ opCode = ((value & 0xff00) != 0) ? THUMB2_PUSH : THUMB_PUSH;
+ break;
+ case OP_POP:
+ opCode = ((value & 0xff00) != 0) ? THUMB2_POP : THUMB_POP;
+ break;
+ default:
+ assert(0);
+ }
+ return newLIR1(cUnit, opCode, value);
+}
+
+static ArmLIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc)
+{
+ ArmOpCode opCode = THUMB_BKPT;
+ switch (op) {
+ case OP_BLX:
+ opCode = THUMB_BLX_R;
+ break;
+ default:
+ assert(0);
+ }
+ return newLIR1(cUnit, opCode, rDestSrc);
+}
+
+static ArmLIR *opRegRegShift(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
+ int rSrc2, int shift)
+{
+ bool thumbForm = ((shift == 0) && LOWREG(rDestSrc1) && LOWREG(rSrc2));
+ ArmOpCode opCode = THUMB_BKPT;
+ switch (op) {
+ case OP_ADC:
+ opCode = (thumbForm) ? THUMB_ADC_RR : THUMB2_ADC_RRR;
+ break;
+ case OP_AND:
+ opCode = (thumbForm) ? THUMB_AND_RR : THUMB2_AND_RRR;
+ break;
+ case OP_BIC:
+ opCode = (thumbForm) ? THUMB_BIC_RR : THUMB2_BIC_RRR;
+ break;
+ case OP_CMN:
+ assert(shift == 0);
+ opCode = (thumbForm) ? THUMB_CMN_RR : THUMB2_CMN_RR;
+ break;
+ case OP_CMP:
+ if (thumbForm)
+ opCode = THUMB_CMP_RR;
+ else if ((shift == 0) && !LOWREG(rDestSrc1) && !LOWREG(rSrc2))
+ opCode = THUMB_CMP_HH;
+ else if ((shift == 0) && LOWREG(rDestSrc1))
+ opCode = THUMB_CMP_LH;
+ else if (shift == 0)
+ opCode = THUMB_CMP_HL;
+ else
+ opCode = THUMB2_CMP_RR;
+ break;
+ case OP_XOR:
+ opCode = (thumbForm) ? THUMB_EOR_RR : THUMB2_EOR_RRR;
+ break;
+ case OP_MOV:
+ assert(shift == 0);
+ if (LOWREG(rDestSrc1) && LOWREG(rSrc2))
+ opCode = THUMB_MOV_RR;
+ else if (!LOWREG(rDestSrc1) && !LOWREG(rSrc2))
+ opCode = THUMB_MOV_RR_H2H;
+ else if (LOWREG(rDestSrc1))
+ opCode = THUMB_MOV_RR_H2L;
+ else
+ opCode = THUMB_MOV_RR_L2H;
+ break;
+ case OP_MUL:
+ assert(shift == 0);
+ opCode = (thumbForm) ? THUMB_MUL : THUMB2_MUL_RRR;
+ break;
+ case OP_MVN:
+ opCode = (thumbForm) ? THUMB_MVN : THUMB2_MVN_RR;
+ break;
+ case OP_NEG:
+ assert(shift == 0);
+ opCode = (thumbForm) ? THUMB_NEG : THUMB2_NEG_RR;
+ break;
+ case OP_OR:
+ opCode = (thumbForm) ? THUMB_ORR : THUMB2_ORR_RRR;
+ break;
+ case OP_SBC:
+ opCode = (thumbForm) ? THUMB_SBC : THUMB2_SBC_RRR;
+ break;
+ case OP_TST:
+ opCode = (thumbForm) ? THUMB_TST : THUMB2_TST_RR;
+ break;
+ case OP_LSL:
+ assert(shift == 0);
+ opCode = (thumbForm) ? THUMB_LSL_RR : THUMB2_LSL_RRR;
+ break;
+ case OP_LSR:
+ assert(shift == 0);
+ opCode = (thumbForm) ? THUMB_LSR_RR : THUMB2_LSR_RRR;
+ break;
+ case OP_ASR:
+ assert(shift == 0);
+ opCode = (thumbForm) ? THUMB_ASR_RR : THUMB2_ASR_RRR;
+ break;
+ case OP_ROR:
+ assert(shift == 0);
+ opCode = (thumbForm) ? THUMB_ROR_RR : THUMB2_ROR_RRR;
+ break;
+ case OP_ADD:
+ opCode = (thumbForm) ? THUMB_ADD_RRR : THUMB2_ADD_RRR;
+ break;
+ case OP_SUB:
+ opCode = (thumbForm) ? THUMB_SUB_RRR : THUMB2_SUB_RRR;
+ break;
+ case OP_2BYTE:
+ assert(shift == 0);
+ return newLIR4(cUnit, THUMB2_SBFX, rDestSrc1, rSrc2, 0, 8);
+ case OP_2SHORT:
+ assert(shift == 0);
+ return newLIR4(cUnit, THUMB2_SBFX, rDestSrc1, rSrc2, 0, 16);
+ case OP_2CHAR:
+ assert(shift == 0);
+ return newLIR4(cUnit, THUMB2_UBFX, rDestSrc1, rSrc2, 0, 16);
+ default:
+ assert(0);
+ break;
+ }
+ assert(opCode >= 0);
+ if (EncodingMap[opCode].flags & IS_BINARY_OP)
+ return newLIR2(cUnit, opCode, rDestSrc1, rSrc2);
+ else if (EncodingMap[opCode].flags & IS_TERTIARY_OP) {
+ if (EncodingMap[opCode].fieldLoc[2].kind == SHIFT)
+ return newLIR3(cUnit, opCode, rDestSrc1, rSrc2, shift);
+ else
+ return newLIR3(cUnit, opCode, rDestSrc1, rDestSrc1, rSrc2);
+ } else if (EncodingMap[opCode].flags & IS_QUAD_OP)
+ return newLIR4(cUnit, opCode, rDestSrc1, rDestSrc1, rSrc2, shift);
+ else {
+ assert(0);
+ return NULL;
+ }
+}
+
+static ArmLIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
+ int rSrc2)
+{
+ return opRegRegShift(cUnit, op, rDestSrc1, rSrc2, 0);
+}
+
+/* Handle Thumb-only variants here - otherwise punt to opRegRegImm */
+static ArmLIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
+ int value, int rScratch)
+{
+ ArmLIR *res;
+ bool neg = (value < 0);
+ int absValue = (neg) ? -value : value;
+ bool shortForm = (((absValue & 0xff) == absValue) && LOWREG(rDestSrc1));
+ ArmOpCode opCode = THUMB_BKPT;
+ switch (op) {
+ case OP_ADD:
+ if ( !neg && (rDestSrc1 == 13) && (value <= 508)) { /* sp */
+ assert((value & 0x3) == 0);
+ return newLIR1(cUnit, THUMB_ADD_SPI7, value >> 2);
+ } else if (shortForm) {
+ opCode = (neg) ? THUMB_SUB_RI8 : THUMB_ADD_RI8;
+ }
+ break;
+ case OP_SUB:
+ if (!neg && (rDestSrc1 == 13) && (value <= 508)) { /* sp */
+ assert((value & 0x3) == 0);
+ return newLIR1(cUnit, THUMB_SUB_SPI7, value >> 2);
+ } else if (shortForm) {
+ opCode = (neg) ? THUMB_ADD_RI8 : THUMB_SUB_RI8;
+ }
+ break;
+ case OP_CMP:
+ if (LOWREG(rDestSrc1) && shortForm)
+ opCode = (shortForm) ? THUMB_CMP_RI8 : THUMB_CMP_RR;
+ else if (LOWREG(rDestSrc1))
+ opCode = THUMB_CMP_RR;
+ else {
+ shortForm = false;
+ opCode = THUMB_CMP_HL;
+ }
+ break;
+ default:
+ /* Punt to opRegRegImm - if bad case catch it there */
+ shortForm = false;
+ break;
+ }
+ if (shortForm)
+ return newLIR2(cUnit, opCode, rDestSrc1, absValue);
+ else
+ return opRegRegImm(cUnit, op, rDestSrc1, rDestSrc1, value, rScratch);
+}
+
+static ArmLIR *opRegRegRegShift(CompilationUnit *cUnit, OpKind op,
+ int rDest, int rSrc1, int rSrc2, int shift)
+{
+ ArmOpCode opCode = THUMB_BKPT;
+ bool thumbForm = (shift == 0) && LOWREG(rDest) && LOWREG(rSrc1) &&
+ LOWREG(rSrc2);
+ switch (op) {
+ case OP_ADD:
+ opCode = (thumbForm) ? THUMB_ADD_RRR : THUMB2_ADD_RRR;
+ break;
+ case OP_SUB:
+ opCode = (thumbForm) ? THUMB_SUB_RRR : THUMB2_SUB_RRR;
+ break;
+ case OP_ADC:
+ opCode = THUMB2_ADC_RRR;
+ break;
+ case OP_AND:
+ opCode = THUMB2_AND_RRR;
+ break;
+ case OP_BIC:
+ opCode = THUMB2_BIC_RRR;
+ break;
+ case OP_XOR:
+ opCode = THUMB2_EOR_RRR;
+ break;
+ case OP_MUL:
+ assert(shift == 0);
+ opCode = THUMB2_MUL_RRR;
+ break;
+ case OP_OR:
+ opCode = THUMB2_ORR_RRR;
+ break;
+ case OP_SBC:
+ opCode = THUMB2_SBC_RRR;
+ break;
+ case OP_LSL:
+ assert(shift == 0);
+ opCode = THUMB2_LSL_RRR;
+ break;
+ case OP_LSR:
+ assert(shift == 0);
+ opCode = THUMB2_LSR_RRR;
+ break;
+ case OP_ASR:
+ assert(shift == 0);
+ opCode = THUMB2_ASR_RRR;
+ break;
+ case OP_ROR:
+ assert(shift == 0);
+ opCode = THUMB2_ROR_RRR;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ assert(opCode >= 0);
+ if (EncodingMap[opCode].flags & IS_QUAD_OP)
+ return newLIR4(cUnit, opCode, rDest, rSrc1, rSrc2, shift);
+ else {
+ assert(EncodingMap[opCode].flags & IS_TERTIARY_OP);
+ return newLIR3(cUnit, opCode, rDest, rSrc1, rSrc2);
+ }
+}
+
+static ArmLIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest,
+ int rSrc1, int rSrc2)
+{
+ return opRegRegRegShift(cUnit, op, rDest, rSrc1, rSrc2, 0);
+}
+
+static ArmLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
+ int rSrc1, int value, int rScratch)
+{
+ ArmLIR *res;
+ bool neg = (value < 0);
+ int absValue = (neg) ? -value : value;
+ ArmOpCode opCode = THUMB_BKPT;
+ ArmOpCode altOpCode = THUMB_BKPT;
+ bool allLowRegs = (LOWREG(rDest) && LOWREG(rSrc1));
+ int modImm = modifiedImmediate(value);
+ int modImmNeg = modifiedImmediate(-value);
+
+ switch(op) {
+ case OP_LSL:
+ if (allLowRegs)
+ return newLIR3(cUnit, THUMB_LSL_RRI5, rDest, rSrc1, value);
+ else
+ return newLIR3(cUnit, THUMB2_LSL_RRI5, rDest, rSrc1, value);
+ case OP_LSR:
+ if (allLowRegs)
+ return newLIR3(cUnit, THUMB_LSR_RRI5, rDest, rSrc1, value);
+ else
+ return newLIR3(cUnit, THUMB2_LSR_RRI5, rDest, rSrc1, value);
+ case OP_ASR:
+ if (allLowRegs)
+ return newLIR3(cUnit, THUMB_ASR_RRI5, rDest, rSrc1, value);
+ else
+ return newLIR3(cUnit, THUMB2_ASR_RRI5, rDest, rSrc1, value);
+ case OP_ROR:
+ return newLIR3(cUnit, THUMB2_ROR_RRI5, rDest, rSrc1, value);
+ case OP_ADD:
+ if (LOWREG(rDest) && (rSrc1 == 13) &&
+ (value <= 1020) && ((value & 0x3)==0)) {
+ return newLIR3(cUnit, THUMB_ADD_SP_REL, rDest, rSrc1,
+ value >> 2);
+ } else if (LOWREG(rDest) && (rSrc1 == rpc) &&
+ (value <= 1020) && ((value & 0x3)==0)) {
+ return newLIR3(cUnit, THUMB_ADD_PC_REL, rDest, rSrc1,
+ value >> 2);
+ }
+ opCode = THUMB2_ADD_RRI8;
+ altOpCode = THUMB2_ADD_RRR;
+ // Note: intentional fallthrough
+ case OP_SUB:
+ if (allLowRegs && ((absValue & 0x7) == absValue)) {
+ if (op == OP_ADD)
+ opCode = (neg) ? THUMB_SUB_RRI3 : THUMB_ADD_RRI3;
+ else
+ opCode = (neg) ? THUMB_ADD_RRI3 : THUMB_SUB_RRI3;
+ return newLIR3(cUnit, opCode, rDest, rSrc1, absValue);
+ } else if ((absValue & 0xff) == absValue) {
+ if (op == OP_ADD)
+ opCode = (neg) ? THUMB2_SUB_RRI12 : THUMB2_ADD_RRI12;
+ else
+ opCode = (neg) ? THUMB2_ADD_RRI12 : THUMB2_SUB_RRI12;
+ return newLIR3(cUnit, opCode, rDest, rSrc1, absValue);
+ }
+ if (modImmNeg >= 0) {
+ op = (op == OP_ADD) ? OP_SUB : OP_ADD;
+ modImm = modImmNeg;
+ }
+ if (op == OP_SUB) {
+ opCode = THUMB2_SUB_RRI8;
+ altOpCode = THUMB2_SUB_RRR;
+ }
+ break;
+ case OP_ADC:
+ opCode = THUMB2_ADC_RRI8;
+ altOpCode = THUMB2_ADC_RRR;
+ break;
+ case OP_SBC:
+ opCode = THUMB2_SBC_RRI8;
+ altOpCode = THUMB2_SBC_RRR;
+ break;
+ case OP_OR:
+ opCode = THUMB2_ORR_RRI8;
+ altOpCode = THUMB2_ORR_RRR;
+ break;
+ case OP_AND:
+ opCode = THUMB2_AND_RRI8;
+ altOpCode = THUMB2_AND_RRR;
+ break;
+ case OP_XOR:
+ opCode = THUMB2_EOR_RRI8;
+ altOpCode = THUMB2_EOR_RRR;
+ break;
+ case OP_MUL:
+ //TUNING: power of 2, shift & add
+ modImm = -1;
+ altOpCode = THUMB2_MUL_RRR;
+ break;
+ default:
+ assert(0);
+ }
+
+ if (modImm >= 0) {
+ return newLIR3(cUnit, opCode, rDest, rSrc1, modImm);
+ } else {
+ loadConstant(cUnit, rScratch, value);
+ if (EncodingMap[altOpCode].flags & IS_QUAD_OP)
+ return newLIR4(cUnit, altOpCode, rDest, rSrc1, rScratch, 0);
+ else
+ return newLIR3(cUnit, altOpCode, rDest, rSrc1, rScratch);
+ }
+}
+
+/*
+ * 64-bit 3way compare function.
+ * mov r7, #-1
+ * cmp op1hi, op2hi
+ * blt done
+ * bgt flip
+ * sub r7, op1lo, op2lo (treat as unsigned)
+ * beq done
+ * ite hi
+ * mov(hi) r7, #-1
+ * mov(!hi) r7, #1
+ * flip:
+ * neg r7
+ * done:
+ */
+static void genCmpLong(CompilationUnit *cUnit, MIR *mir,
+ int vDest, int vSrc1, int vSrc2)
+{
+ int op1lo = selectFirstRegister(cUnit, vSrc1, true);
+ int op1hi = NEXT_REG(op1lo);
+ int op2lo = NEXT_REG(op1hi);
+ int op2hi = NEXT_REG(op2lo);
+ loadValuePair(cUnit, vSrc1, op1lo, op1hi);
+ loadValuePair(cUnit, vSrc2, op2lo, op2hi);
+ /* Note: using hardcoded r7 & r4PC for now. revisit */
+ loadConstant(cUnit, r7, -1);
+ opRegReg(cUnit, OP_CMP, op1hi, op2hi);
+ ArmLIR *branch1 = opCondBranch(cUnit, ARM_COND_LT);
+ ArmLIR *branch2 = opCondBranch(cUnit, ARM_COND_GT);
+ opRegRegReg(cUnit, OP_SUB, r7, op1lo, op2lo);
+ ArmLIR *branch3 = opCondBranch(cUnit, ARM_COND_EQ);
+
+ // TODO: need assert mechanism to verify IT block size
+ branch1->generic.target = (LIR *) genIT(cUnit, ARM_COND_HI, "E");
+ newLIR2(cUnit, THUMB2_MOV_IMM_SHIFT, r7, modifiedImmediate(-1));
+ newLIR2(cUnit, THUMB_MOV_IMM, r7, 1);
+ genBarrier(cUnit);
+
+ branch2->generic.target = (LIR *) opRegReg(cUnit, OP_NEG, r7, r7);
+ branch1->generic.target = (LIR *) storeValue(cUnit, r7, vDest, r4PC);
+ branch3->generic.target = branch1->generic.target;
+}
+
+static bool genInlinedStringLength(CompilationUnit *cUnit, MIR *mir)
+{
+ DecodedInstruction *dInsn = &mir->dalvikInsn;
+ int offset = offsetof(InterpState, retval);
+ int regObj = selectFirstRegister(cUnit, dInsn->arg[0], false);
+ int reg1 = NEXT_REG(regObj);
+ int vDest = inlinedTarget(mir);
+ loadValue(cUnit, dInsn->arg[0], regObj);
+ genNullCheck(cUnit, dInsn->arg[0], regObj, mir->offset, NULL);
+ loadWordDisp(cUnit, regObj, gDvm.offJavaLangString_count, reg1);
+ if (vDest >= 0)
+ storeValue(cUnit, reg1, vDest, regObj);
+ else
+ storeWordDisp(cUnit, rGLUE, offset, reg1, rNone);
+ return false;
+}
+
+static bool genInlinedStringCharAt(CompilationUnit *cUnit, MIR *mir)
+{
+ DecodedInstruction *dInsn = &mir->dalvikInsn;
+ int offset = offsetof(InterpState, retval);
+ int contents = offsetof(ArrayObject, contents);
+ int regObj = selectFirstRegister(cUnit, dInsn->arg[0], false);
+ int regIdx = NEXT_REG(regObj);
+ int regMax = NEXT_REG(regIdx);
+ int regOff = NEXT_REG(regMax);
+ int vDest = inlinedTarget(mir);
+ loadValue(cUnit, dInsn->arg[0], regObj);
+ loadValue(cUnit, dInsn->arg[1], regIdx);
+ ArmLIR * pcrLabel = genNullCheck(cUnit, dInsn->arg[0], regObj,
+ mir->offset, NULL);
+ loadWordDisp(cUnit, regObj, gDvm.offJavaLangString_count, regMax);
+ loadWordDisp(cUnit, regObj, gDvm.offJavaLangString_offset, regOff);
+ loadWordDisp(cUnit, regObj, gDvm.offJavaLangString_value, regObj);
+ genBoundsCheck(cUnit, regIdx, regMax, mir->offset, pcrLabel);
+ opRegImm(cUnit, OP_ADD, regObj, contents, rNone);
+ opRegReg(cUnit, OP_ADD, regIdx, regOff);
+ loadBaseIndexed(cUnit, regObj, regIdx, regMax, 1, UNSIGNED_HALF);
+ if (vDest >= 0)
+ storeValue(cUnit, regMax, vDest, regObj);
+ else
+ storeWordDisp(cUnit, rGLUE, offset, regMax, rNone);
+ return false;
+}
+
+static bool genInlinedAbsInt(CompilationUnit *cUnit, MIR *mir)
+{
+ int offset = offsetof(InterpState, retval);
+ DecodedInstruction *dInsn = &mir->dalvikInsn;
+ int reg0 = selectFirstRegister(cUnit, dInsn->arg[0], false);
+ int sign = NEXT_REG(reg0);
+ int vDest = inlinedTarget(mir);
+ /* abs(x) = y<=x>>31, (x+y)^y. */
+ loadValue(cUnit, dInsn->arg[0], reg0);
+ /*
+ * Thumb2's IT block also yields 3 instructions, but imposes
+ * scheduling constraints.
+ */
+ opRegRegImm(cUnit, OP_ASR, sign, reg0, 31, rNone);
+ opRegReg(cUnit, OP_ADD, reg0, sign);
+ opRegReg(cUnit, OP_XOR, reg0, sign);
+ if (vDest >= 0)
+ storeValue(cUnit, reg0, vDest, sign);
+ else
+ storeWordDisp(cUnit, rGLUE, offset, reg0, rNone);
+ return false;
+}
+
+static bool genInlinedAbsFloat(CompilationUnit *cUnit, MIR *mir)
+{
+ int offset = offsetof(InterpState, retval);
+ DecodedInstruction *dInsn = &mir->dalvikInsn;
+ int reg0 = selectFirstRegister(cUnit, dInsn->arg[0], false);
+ int signMask = NEXT_REG(reg0);
+ int vDest = inlinedTarget(mir);
+ // TUNING: handle case of src already in FP reg
+ loadValue(cUnit, dInsn->arg[0], reg0);
+ loadConstant(cUnit, signMask, 0x7fffffff);
+ newLIR2(cUnit, THUMB_AND_RR, reg0, signMask);
+ if (vDest >= 0)
+ storeValue(cUnit, reg0, vDest, signMask);
+ else
+ storeWordDisp(cUnit, rGLUE, offset, reg0, rNone);
+ return false;
+}
+
+static bool genInlinedAbsDouble(CompilationUnit *cUnit, MIR *mir)
+{
+ int offset = offsetof(InterpState, retval);
+ DecodedInstruction *dInsn = &mir->dalvikInsn;
+ int oplo = selectFirstRegister(cUnit, dInsn->arg[0], true);
+ int ophi = NEXT_REG(oplo);
+ int signMask = NEXT_REG(ophi);
+ int vSrc = dInsn->arg[0];
+ int vDest = inlinedTarget(mir);
+ // TUNING: handle case of src already in FP reg
+ if (vDest >= 0) {
+ /*
+ * FIXME: disable this case to to work around bug until after
+ * new schedule/ralloc mechanisms are done.
+ */
+ if (0 && (vDest == vSrc)) {
+ loadValue(cUnit, vSrc+1, ophi);
+ opRegRegImm(cUnit, OP_AND, ophi, ophi, 0x7fffffff, signMask);
+ storeValue(cUnit, ophi, vDest + 1, signMask);
+ } else {
+ loadValuePair(cUnit, dInsn->arg[0], oplo, ophi);
+ opRegRegImm(cUnit, OP_AND, ophi, ophi, 0x7fffffff, signMask);
+ storeValuePair(cUnit, oplo, ophi, vDest, signMask);
+ }
+ } else {
+ loadValuePair(cUnit, dInsn->arg[0], oplo, ophi);
+ loadConstant(cUnit, signMask, 0x7fffffff);
+ storeWordDisp(cUnit, rGLUE, offset, oplo, rNone);
+ opRegReg(cUnit, OP_AND, ophi, signMask);
+ storeWordDisp(cUnit, rGLUE, offset + 4, ophi, rNone);
+ }
+ return false;
+}
+
+static bool genInlinedMinMaxInt(CompilationUnit *cUnit, MIR *mir, bool isMin)
+{
+ int offset = offsetof(InterpState, retval);
+ DecodedInstruction *dInsn = &mir->dalvikInsn;
+ int reg0 = selectFirstRegister(cUnit, dInsn->arg[0], false);
+ int reg1 = NEXT_REG(reg0);
+ int vDest = inlinedTarget(mir);
+ loadValue(cUnit, dInsn->arg[0], reg0);
+ loadValue(cUnit, dInsn->arg[1], reg1);
+ opRegReg(cUnit, OP_CMP, reg0, reg1);
+ //TODO: need assertion mechanism to validate IT region size
+ genIT(cUnit, (isMin) ? ARM_COND_GT : ARM_COND_LT, "");
+ opRegReg(cUnit, OP_MOV, reg0, reg1);
+ genBarrier(cUnit);
+ if (vDest >= 0)
+ storeValue(cUnit, reg0, vDest, reg1);
+ else
+ storeWordDisp(cUnit, rGLUE, offset, reg0, rNone);
+ return false;
+}
+
+static bool genInlinedAbsLong(CompilationUnit *cUnit, MIR *mir)
+{
+ int offset = offsetof(InterpState, retval);
+ DecodedInstruction *dInsn = &mir->dalvikInsn;
+ int oplo = selectFirstRegister(cUnit, dInsn->arg[0], true);
+ int ophi = NEXT_REG(oplo);
+ int sign = NEXT_REG(ophi);
+ int vDest = inlinedTarget(mir);
+ /* abs(x) = y<=x>>31, (x+y)^y. */
+ loadValuePair(cUnit, dInsn->arg[0], oplo, ophi);
+ /*
+ * Thumb2 IT block allows slightly shorter sequence,
+ * but introduces a scheduling barrier. Stick with this
+ * mechanism for now.
+ */
+ opRegRegImm(cUnit, OP_ASR, sign, ophi, 31, rNone);
+ opRegReg(cUnit, OP_ADD, oplo, sign);
+ opRegReg(cUnit, OP_ADC, ophi, sign);
+ opRegReg(cUnit, OP_XOR, oplo, sign);
+ opRegReg(cUnit, OP_XOR, ophi, sign);
+ if (vDest >= 0) {
+ storeValuePair(cUnit, oplo, ophi, vDest, sign);
+ } else {
+ storeWordDisp(cUnit, rGLUE, offset, oplo, rNone);
+ storeWordDisp(cUnit, rGLUE, offset + 4, ophi, rNone);
+ }
+ return false;
+}
diff --git a/vm/compiler/codegen/arm/ThumbUtil.c b/vm/compiler/codegen/arm/ThumbUtil.c
index 8be50ad..4065865 100644
--- a/vm/compiler/codegen/arm/ThumbUtil.c
+++ b/vm/compiler/codegen/arm/ThumbUtil.c
@@ -16,46 +16,89 @@
/*
* This file contains codegen for the Thumb ISA and is intended to be
- * includes by:and support common to all supported
+ * includes by:
*
* Codegen-$(TARGET_ARCH_VARIANT).c
*
*/
#include "Codegen.h"
+/* Forward decls */
+static ArmLIR *genNullCheck(CompilationUnit *cUnit, int vReg, int mReg,
+ int dOffset, ArmLIR *pcrLabel);
+static ArmLIR *loadValueAddress(CompilationUnit *cUnit, int vSrc, int rDest);
+static ArmLIR *loadValue(CompilationUnit *cUnit, int vSrc, int rDest);
+static ArmLIR *loadWordDisp(CompilationUnit *cUnit, int rBase,
+ int displacement, int rDest);
+static ArmLIR *storeWordDisp(CompilationUnit *cUnit, int rBase,
+ int displacement, int rSrc, int rScratch);
+static ArmLIR *storeValue(CompilationUnit *cUnit, int rSrc, int vDest,
+ int rScratch);
+static ArmLIR *genConditionalBranch(CompilationUnit *cUnit,
+ ArmConditionCode cond,
+ ArmLIR *target);
+static ArmLIR *genUnconditionalBranch(CompilationUnit *cUnit, ArmLIR *target);
+static ArmLIR *loadValuePair(CompilationUnit *cUnit, int vSrc, int rDestLo,
+ int rDestHi);
+static ArmLIR *storeValuePair(CompilationUnit *cUnit, int rSrcLo, int rSrcHi,
+ int vDest, int rScratch);
+static ArmLIR *genBoundsCheck(CompilationUnit *cUnit, int rIndex,
+ int rBound, int dOffset, ArmLIR *pcrLabel);
+static ArmLIR *genRegCopy(CompilationUnit *cUnit, int rDest, int rSrc);
+static int inlinedTarget(MIR *mir);
+
/* Routines which must be supplied here */
-static void loadConstant(CompilationUnit *cUnit, int rDest, int value);
-static void genExportPC(CompilationUnit *cUnit, MIR *mir, int rDPC, int rAddr);
-static void genConditionalBranch(CompilationUnit *cUnit,
- ArmConditionCode cond,
- ArmLIR *target);
-static ArmLIR *genUnconditionalBranch(CompilationUnit *cUnit, ArmLIR *target);
-static void loadValuePair(CompilationUnit *cUnit, int vSrc, int rDestLo,
- int rDestHi);
-static void storeValuePair(CompilationUnit *cUnit, int rSrcLo, int rSrcHi,
- int vDest, int rScratch);
-static void loadValueAddress(CompilationUnit *cUnit, int vSrc, int vDest);
-static void loadValue(CompilationUnit *cUnit, int vSrc, int rDest);
-static void loadWordDisp(CompilationUnit *cUnit, int rBase, int displacement,
- int rDest);
-static void storeValue(CompilationUnit *cUnit, int rSrc, int vDest,
- int rScratch);
+static ArmLIR *loadConstant(CompilationUnit *cUnit, int rDest, int value);
+static ArmLIR *genExportPC(CompilationUnit *cUnit, MIR *mir, int rDPC,
+ int rAddr);
+static ArmLIR *loadBaseDisp(CompilationUnit *cUnit, MIR *mir, int rBase,
+ int displacement, int rDest, OpSize size,
+ bool nullCheck, int vReg);
+static ArmLIR *storeBaseDisp(CompilationUnit *cUnit, int rBase,
+ int displacement, int rSrc, OpSize size,
+ int rScratch);
static inline ArmLIR *genRegImmCheck(CompilationUnit *cUnit,
- ArmConditionCode cond, int reg,
- int checkValue, int dOffset,
- ArmLIR *pcrLabel);
+ ArmConditionCode cond, int reg,
+ int checkValue, int dOffset,
+ ArmLIR *pcrLabel);
+static inline ArmLIR *genRegRegCheck(CompilationUnit *cUnit,
+ ArmConditionCode cond,
+ int reg1, int reg2, int dOffset,
+ ArmLIR *pcrLabel);
ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc);
+static ArmLIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask);
+static ArmLIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask);
-/*****************************************************************************/
+static ArmLIR *opNone(CompilationUnit *cUnit, OpKind op);
+static ArmLIR *opImm(CompilationUnit *cUnit, OpKind op, int value);
+static ArmLIR *opCondBranch(CompilationUnit *cUnit, ArmConditionCode cc);
+static ArmLIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc);
+static ArmLIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
+ int rSrc2);
+static ArmLIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
+ int value, int rScratch);
+static ArmLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
+ int rSrc1, int value, int rScratch);
+static ArmLIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest,
+ int rSrc1, int rSrc2);
+static ArmLIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase,
+ int rIndex, int rDest, int scale, OpSize size);
+static void genCmpLong(CompilationUnit *cUnit, MIR *mir, int vDest, int vSrc1,
+ int vSrc2);
+
+static bool genInlinedStringLength(CompilationUnit *cUnit, MIR *mir);
+static bool genInlinedStringCharAt(CompilationUnit *cUnit, MIR *mir);
+static bool genInlinedAbsInt(CompilationUnit *cUnit, MIR *mir);
+static bool genInlinedAbsFloat(CompilationUnit *cUnit, MIR *mir);
+static bool genInlinedAbsDouble(CompilationUnit *cUnit, MIR *mir);
+static bool genInlinedMinMaxInt(CompilationUnit *cUnit, MIR *mir, bool isMin);
+static bool genInlinedAbsLong(CompilationUnit *cUnit, MIR *mir);
/*
* Support for register allocation
*/
-/* non-existent register */
-#define vNone (-1)
-
/* get the next register in r0..r3 in a round-robin fashion */
#define NEXT_REG(reg) ((reg + 1) & 3)
/*
@@ -131,15 +174,24 @@
}
-/*****************************************************************************/
-
ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
{
- ArmLIR* res = dvmCompilerNew(sizeof(ArmLIR), true);
- assert(LOWREG(rDest) && LOWREG(rSrc));
+ ArmLIR* res;
+ ArmOpCode opCode;
+ res = dvmCompilerNew(sizeof(ArmLIR), true);
+ if (LOWREG(rDest) && LOWREG(rSrc))
+ opCode = THUMB_MOV_RR;
+ else if (!LOWREG(rDest) && !LOWREG(rSrc))
+ opCode = THUMB_MOV_RR_H2H;
+ else if (LOWREG(rDest))
+ opCode = THUMB_MOV_RR_H2L;
+ else
+ opCode = THUMB_MOV_RR_L2H;
+
res->operands[0] = rDest;
res->operands[1] = rSrc;
- res->opCode = THUMB_MOV_RR;
+ res->opCode = opCode;
+ setupResourceMasks(res);
if (rDest == rSrc) {
res->isNop = true;
}
@@ -150,16 +202,16 @@
* Load a immediate using a shortcut if possible; otherwise
* grab from the per-translation literal pool
*/
-static void loadConstant(CompilationUnit *cUnit, int rDest, int value)
+static ArmLIR *loadConstant(CompilationUnit *cUnit, int rDest, int value)
{
+ ArmLIR *res;
/* See if the value can be constructed cheaply */
if ((value >= 0) && (value <= 255)) {
- newLIR2(cUnit, THUMB_MOV_IMM, rDest, value);
- return;
+ return newLIR2(cUnit, THUMB_MOV_IMM, rDest, value);
} else if ((value & 0xFFFFFF00) == 0xFFFFFF00) {
- newLIR2(cUnit, THUMB_MOV_IMM, rDest, ~value);
+ res = newLIR2(cUnit, THUMB_MOV_IMM, rDest, ~value);
newLIR2(cUnit, THUMB_MVN, rDest, rDest);
- return;
+ return res;
}
/* No shortcut - go ahead and use literal pool */
ArmLIR *dataTarget = scanLiteralPool(cUnit, value, 255);
@@ -170,6 +222,8 @@
loadPcRel->opCode = THUMB_LDR_PC_REL;
loadPcRel->generic.target = (LIR *) dataTarget;
loadPcRel->operands[0] = rDest;
+ setupResourceMasks(loadPcRel);
+ res = loadPcRel;
dvmCompilerAppendLIR(cUnit, (LIR *) loadPcRel);
/*
@@ -179,147 +233,221 @@
if (dataTarget->operands[0] != value) {
newLIR2(cUnit, THUMB_ADD_RI8, rDest, value - dataTarget->operands[0]);
}
+ return res;
}
/* Export the Dalvik PC assicated with an instruction to the StackSave area */
-static void genExportPC(CompilationUnit *cUnit, MIR *mir, int rDPC, int rAddr)
+static ArmLIR *genExportPC(CompilationUnit *cUnit, MIR *mir, int rDPC,
+ int rAddr)
{
+ ArmLIR *res;
int offset = offsetof(StackSaveArea, xtra.currentPc);
- loadConstant(cUnit, rDPC, (int) (cUnit->method->insns + mir->offset));
+ res = loadConstant(cUnit, rDPC, (int) (cUnit->method->insns + mir->offset));
newLIR2(cUnit, THUMB_MOV_RR, rAddr, rFP);
newLIR2(cUnit, THUMB_SUB_RI8, rAddr, sizeof(StackSaveArea) - offset);
- newLIR3(cUnit, THUMB_STR_RRI5, rDPC, rAddr, 0);
+ storeWordDisp( cUnit, rAddr, 0, rDPC, -1);
+ return res;
}
-/* Generate conditional branch instructions */
-static void genConditionalBranch(CompilationUnit *cUnit,
- ArmConditionCode cond,
- ArmLIR *target)
+/* Load value from base + scaled index. Note: index reg killed */
+static ArmLIR *loadBaseIndexed(CompilationUnit *cUnit, int rBase,
+ int rIndex, int rDest, int scale, OpSize size)
{
- ArmLIR *branch = newLIR2(cUnit, THUMB_B_COND, 0, cond);
- branch->generic.target = (LIR *) target;
+ ArmLIR *first = NULL;
+ ArmLIR *res;
+ ArmOpCode opCode = THUMB_BKPT;
+ if (scale)
+ first = opRegRegImm(cUnit, OP_LSL, rIndex, rIndex, scale, rNone);
+ switch (size) {
+ case WORD:
+ opCode = THUMB_LDR_RRR;
+ break;
+ case UNSIGNED_HALF:
+ opCode = THUMB_LDRH_RRR;
+ break;
+ case SIGNED_HALF:
+ opCode = THUMB_LDRSH_RRR;
+ break;
+ case UNSIGNED_BYTE:
+ opCode = THUMB_LDRB_RRR;
+ break;
+ case SIGNED_BYTE:
+ opCode = THUMB_LDRSB_RRR;
+ break;
+ default:
+ assert(0);
+ }
+ res = newLIR3(cUnit, opCode, rDest, rBase, rIndex);
+ return (first) ? first : res;
}
-/* Generate unconditional branch instructions */
-static ArmLIR *genUnconditionalBranch(CompilationUnit *cUnit, ArmLIR *target)
+/* store value base base + scaled index. Note: index reg killed */
+static ArmLIR *storeBaseIndexed(CompilationUnit *cUnit, int rBase,
+ int rIndex, int rSrc, int scale, OpSize size)
{
- ArmLIR *branch = newLIR0(cUnit, THUMB_B_UNCOND);
- branch->generic.target = (LIR *) target;
- return branch;
+ ArmLIR *first = NULL;
+ ArmLIR *res;
+ ArmOpCode opCode = THUMB_BKPT;
+ if (scale)
+ first = opRegRegImm(cUnit, OP_LSL, rIndex, rIndex, scale, rNone);
+ switch (size) {
+ case WORD:
+ opCode = THUMB_STR_RRR;
+ break;
+ case UNSIGNED_HALF:
+ case SIGNED_HALF:
+ opCode = THUMB_STRH_RRR;
+ break;
+ case UNSIGNED_BYTE:
+ case SIGNED_BYTE:
+ opCode = THUMB_STRB_RRR;
+ break;
+ default:
+ assert(0);
+ }
+ res = newLIR3(cUnit, opCode, rSrc, rBase, rIndex);
+ return (first) ? first : res;
}
/*
- * Load a pair of values of rFP[src..src+1] and store them into rDestLo and
- * rDestHi
+ * Load value from base + displacement. Optionally perform null check
+ * on base (which must have an associated vReg and MIR). If not
+ * performing null check, incoming MIR can be null. Note: base and
+ * dest must not be the same if there is any chance that the long
+ * form must be used.
*/
-static void loadValuePair(CompilationUnit *cUnit, int vSrc, int rDestLo,
- int rDestHi)
+static ArmLIR *loadBaseDisp(CompilationUnit *cUnit, MIR *mir, int rBase,
+ int displacement, int rDest, OpSize size,
+ bool nullCheck, int vReg)
{
- /* Use reg + imm5*4 to load the values if possible */
- if (vSrc <= 30) {
- newLIR3(cUnit, THUMB_LDR_RRI5, rDestLo, rFP, vSrc);
- newLIR3(cUnit, THUMB_LDR_RRI5, rDestHi, rFP, vSrc+1);
- } else {
- if (vSrc <= 64) {
- /* Sneak 4 into the base address first */
- newLIR3(cUnit, THUMB_ADD_RRI3, rDestLo, rFP, 4);
- newLIR2(cUnit, THUMB_ADD_RI8, rDestLo, (vSrc-1)*4);
- } else {
- /* Offset too far from rFP */
- loadConstant(cUnit, rDestLo, vSrc*4);
- newLIR3(cUnit, THUMB_ADD_RRR, rDestLo, rFP, rDestLo);
- }
- assert(rDestLo < rDestHi);
- newLIR2(cUnit, THUMB_LDMIA, rDestLo, (1<<rDestLo) | (1<<(rDestHi)));
+ ArmLIR *first = NULL;
+ ArmLIR *res, *load;
+ ArmOpCode opCode = THUMB_BKPT;
+ bool shortForm = false;
+ int shortMax = 128;
+ int encodedDisp = displacement;
+
+ switch (size) {
+ case WORD:
+ if (LOWREG(rDest) && (rBase == rpc) &&
+ (displacement <= 1020) && (displacement >= 0)) {
+ shortForm = true;
+ encodedDisp >>= 2;
+ opCode = THUMB_LDR_PC_REL;
+ } else if (LOWREG(rDest) && (rBase == r13) &&
+ (displacement <= 1020) && (displacement >= 0)) {
+ shortForm = true;
+ encodedDisp >>= 2;
+ opCode = THUMB_LDR_SP_REL;
+ } else if (displacement < 128 && displacement >= 0) {
+ assert((displacement & 0x3) == 0);
+ shortForm = true;
+ encodedDisp >>= 2;
+ opCode = THUMB_LDR_RRI5;
+ } else {
+ opCode = THUMB_LDR_RRR;
+ }
+ break;
+ case UNSIGNED_HALF:
+ if (displacement < 64 && displacement >= 0) {
+ assert((displacement & 0x1) == 0);
+ shortForm = true;
+ encodedDisp >>= 1;
+ opCode = THUMB_LDRH_RRI5;
+ } else {
+ opCode = THUMB_LDRH_RRR;
+ }
+ break;
+ case SIGNED_HALF:
+ opCode = THUMB_LDRSH_RRR;
+ break;
+ case UNSIGNED_BYTE:
+ if (displacement < 32 && displacement >= 0) {
+ shortForm = true;
+ opCode = THUMB_LDRB_RRI5;
+ } else {
+ opCode = THUMB_LDRB_RRR;
+ }
+ break;
+ case SIGNED_BYTE:
+ opCode = THUMB_LDRSB_RRR;
+ break;
+ default:
+ assert(0);
}
+ if (nullCheck)
+ first = genNullCheck(cUnit, vReg, rBase, mir->offset, NULL);
+ if (shortForm) {
+ load = res = newLIR3(cUnit, opCode, rDest, rBase, encodedDisp);
+ } else {
+ assert(rBase != rDest);
+ res = loadConstant(cUnit, rDest, encodedDisp);
+ load = newLIR3(cUnit, opCode, rDest, rBase, rDest);
+ }
+
+ if (rBase == rFP) {
+ annotateDalvikRegAccess(load, displacement >> 2, true /* isLoad */);
+ }
+
+ return (first) ? first : res;
}
-/*
- * Store a pair of values of rSrc and rSrc+1 and store them into vDest and
- * vDest+1
- */
-static void storeValuePair(CompilationUnit *cUnit, int rSrcLo, int rSrcHi,
- int vDest, int rScratch)
+static ArmLIR *storeBaseDisp(CompilationUnit *cUnit, int rBase,
+ int displacement, int rSrc, OpSize size,
+ int rScratch)
{
- killNullCheckedRegister(cUnit, vDest);
- killNullCheckedRegister(cUnit, vDest+1);
- updateLiveRegisterPair(cUnit, vDest, rSrcLo, rSrcHi);
+ ArmLIR *res, *store;
+ ArmOpCode opCode = THUMB_BKPT;
+ bool shortForm = false;
+ int shortMax = 128;
+ int encodedDisp = displacement;
- /* Use reg + imm5*4 to store the values if possible */
- if (vDest <= 30) {
- newLIR3(cUnit, THUMB_STR_RRI5, rSrcLo, rFP, vDest);
- newLIR3(cUnit, THUMB_STR_RRI5, rSrcHi, rFP, vDest+1);
- } else {
- if (vDest <= 64) {
- /* Sneak 4 into the base address first */
- newLIR3(cUnit, THUMB_ADD_RRI3, rScratch, rFP, 4);
- newLIR2(cUnit, THUMB_ADD_RI8, rScratch, (vDest-1)*4);
- } else {
- /* Offset too far from rFP */
- loadConstant(cUnit, rScratch, vDest*4);
- newLIR3(cUnit, THUMB_ADD_RRR, rScratch, rFP, rScratch);
- }
- assert(rSrcLo < rSrcHi);
- newLIR2(cUnit, THUMB_STMIA, rScratch, (1<<rSrcLo) | (1 << (rSrcHi)));
+ switch (size) {
+ case WORD:
+ if (displacement < 128 && displacement >= 0) {
+ assert((displacement & 0x3) == 0);
+ shortForm = true;
+ encodedDisp >>= 2;
+ opCode = THUMB_STR_RRI5;
+ } else {
+ opCode = THUMB_STR_RRR;
+ }
+ break;
+ case UNSIGNED_HALF:
+ case SIGNED_HALF:
+ if (displacement < 64 && displacement >= 0) {
+ assert((displacement & 0x1) == 0);
+ shortForm = true;
+ encodedDisp >>= 1;
+ opCode = THUMB_STRH_RRI5;
+ } else {
+ opCode = THUMB_STRH_RRR;
+ }
+ break;
+ case UNSIGNED_BYTE:
+ case SIGNED_BYTE:
+ if (displacement < 32 && displacement >= 0) {
+ shortForm = true;
+ opCode = THUMB_STRB_RRI5;
+ } else {
+ opCode = THUMB_STRB_RRR;
+ }
+ break;
+ default:
+ assert(0);
}
-}
-
-/* Load the address of a Dalvik register on the frame */
-static void loadValueAddress(CompilationUnit *cUnit, int vSrc, int rDest)
-{
- /* RRI3 can add up to 7 */
- if (vSrc <= 1) {
- newLIR3(cUnit, THUMB_ADD_RRI3, rDest, rFP, vSrc*4);
- } else if (vSrc <= 64) {
- /* Sneak 4 into the base address first */
- newLIR3(cUnit, THUMB_ADD_RRI3, rDest, rFP, 4);
- newLIR2(cUnit, THUMB_ADD_RI8, rDest, (vSrc-1)*4);
+ if (shortForm) {
+ store = res = newLIR3(cUnit, opCode, rSrc, rBase, encodedDisp);
} else {
- loadConstant(cUnit, rDest, vSrc*4);
- newLIR3(cUnit, THUMB_ADD_RRR, rDest, rFP, rDest);
+ assert(rScratch != -1);
+ res = loadConstant(cUnit, rScratch, encodedDisp);
+ store = newLIR3(cUnit, opCode, rSrc, rBase, rScratch);
}
-}
-/* Load a single value from rFP[src] and store them into rDest */
-static void loadValue(CompilationUnit *cUnit, int vSrc, int rDest)
-{
- /* Use reg + imm5*4 to load the value if possible */
- if (vSrc <= 31) {
- newLIR3(cUnit, THUMB_LDR_RRI5, rDest, rFP, vSrc);
- } else {
- loadConstant(cUnit, rDest, vSrc*4);
- newLIR3(cUnit, THUMB_LDR_RRR, rDest, rFP, rDest);
+ if (rBase == rFP) {
+ annotateDalvikRegAccess(store, displacement >> 2, false /* isLoad */);
}
-}
-
-/* Load a word at base + displacement. Displacement must be word multiple */
-static void loadWordDisp(CompilationUnit *cUnit, int rBase, int displacement,
- int rDest)
-{
- assert((displacement & 0x3) == 0);
- /* Can it fit in a RRI5? */
- if (displacement < 128) {
- newLIR3(cUnit, THUMB_LDR_RRI5, rDest, rBase, displacement >> 2);
- } else {
- loadConstant(cUnit, rDest, displacement);
- newLIR3(cUnit, THUMB_LDR_RRR, rDest, rBase, rDest);
- }
-}
-
-/* Store a value from rSrc to vDest */
-static void storeValue(CompilationUnit *cUnit, int rSrc, int vDest,
- int rScratch)
-{
- killNullCheckedRegister(cUnit, vDest);
- updateLiveRegister(cUnit, vDest, rSrc);
-
- /* Use reg + imm5*4 to store the value if possible */
- if (vDest <= 31) {
- newLIR3(cUnit, THUMB_STR_RRI5, rSrc, rFP, vDest);
- } else {
- loadConstant(cUnit, rScratch, vDest*4);
- newLIR3(cUnit, THUMB_STR_RRR, rSrc, rFP, rScratch);
- }
+ return res;
}
/*
@@ -331,7 +459,441 @@
int checkValue, int dOffset,
ArmLIR *pcrLabel)
{
+ if ((checkValue & 0xff) != checkValue) {
+ /* NOTE: direct use of hot temp r7 here. Revisit. */
+ loadConstant(cUnit, r7, checkValue);
+ return genRegRegCheck(cUnit, cond, reg, r7, dOffset, pcrLabel);
+ }
newLIR2(cUnit, THUMB_CMP_RI8, reg, checkValue);
ArmLIR *branch = newLIR2(cUnit, THUMB_B_COND, 0, cond);
return genCheckCommon(cUnit, dOffset, branch, pcrLabel);
}
+
+static ArmLIR *loadMultiple(CompilationUnit *cUnit, int rBase, int rMask)
+{
+ return newLIR2(cUnit, THUMB_LDMIA, rBase, rMask);
+}
+
+static ArmLIR *storeMultiple(CompilationUnit *cUnit, int rBase, int rMask)
+{
+ return newLIR2(cUnit, THUMB_STMIA, rBase, rMask);
+}
+
+static ArmLIR *opNone(CompilationUnit *cUnit, OpKind op)
+{
+ ArmOpCode opCode = THUMB_BKPT;
+ switch (op) {
+ case OP_UNCOND_BR:
+ opCode = THUMB_B_UNCOND;
+ break;
+ default:
+ assert(0);
+ }
+ return newLIR0(cUnit, opCode);
+}
+
+static ArmLIR *opCondBranch(CompilationUnit *cUnit, ArmConditionCode cc)
+{
+ return newLIR2(cUnit, THUMB_B_COND, 0 /* offset to be patched */, cc);
+}
+
+static ArmLIR *opImm(CompilationUnit *cUnit, OpKind op, int value)
+{
+ ArmOpCode opCode = THUMB_BKPT;
+ switch (op) {
+ case OP_PUSH:
+ opCode = THUMB_PUSH;
+ break;
+ case OP_POP:
+ opCode = THUMB_POP;
+ break;
+ default:
+ assert(0);
+ }
+ return newLIR1(cUnit, opCode, value);
+}
+
+static ArmLIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc)
+{
+ ArmOpCode opCode = THUMB_BKPT;
+ switch (op) {
+ case OP_BLX:
+ opCode = THUMB_BLX_R;
+ break;
+ default:
+ assert(0);
+ }
+ return newLIR1(cUnit, opCode, rDestSrc);
+}
+
+static ArmLIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
+ int rSrc2)
+{
+ ArmLIR *res;
+ ArmOpCode opCode = THUMB_BKPT;
+ switch (op) {
+ case OP_ADC:
+ opCode = THUMB_ADC_RR;
+ break;
+ case OP_AND:
+ opCode = THUMB_AND_RR;
+ break;
+ case OP_BIC:
+ opCode = THUMB_BIC_RR;
+ break;
+ case OP_CMN:
+ opCode = THUMB_CMN_RR;
+ break;
+ case OP_CMP:
+ opCode = THUMB_CMP_RR;
+ break;
+ case OP_XOR:
+ opCode = THUMB_EOR_RR;
+ break;
+ case OP_MOV:
+ if (LOWREG(rDestSrc1) && LOWREG(rSrc2))
+ opCode = THUMB_MOV_RR;
+ else if (!LOWREG(rDestSrc1) && !LOWREG(rSrc2))
+ opCode = THUMB_MOV_RR_H2H;
+ else if (LOWREG(rDestSrc1))
+ opCode = THUMB_MOV_RR_H2L;
+ else
+ opCode = THUMB_MOV_RR_L2H;
+ break;
+ case OP_MUL:
+ opCode = THUMB_MUL;
+ break;
+ case OP_MVN:
+ opCode = THUMB_MVN;
+ break;
+ case OP_NEG:
+ opCode = THUMB_NEG;
+ break;
+ case OP_OR:
+ opCode = THUMB_ORR;
+ break;
+ case OP_SBC:
+ opCode = THUMB_SBC;
+ break;
+ case OP_TST:
+ opCode = THUMB_TST;
+ break;
+ case OP_LSL:
+ opCode = THUMB_LSL_RR;
+ break;
+ case OP_LSR:
+ opCode = THUMB_LSR_RR;
+ break;
+ case OP_ASR:
+ opCode = THUMB_ASR_RR;
+ break;
+ case OP_ROR:
+ opCode = THUMB_ROR_RR;
+ case OP_ADD:
+ case OP_SUB:
+ return opRegRegReg(cUnit, op, rDestSrc1, rDestSrc1, rSrc2);
+ case OP_2BYTE:
+ res = opRegRegImm(cUnit, OP_LSL, rDestSrc1, rSrc2, 24, rNone);
+ opRegRegImm(cUnit, OP_ASR, rDestSrc1, rDestSrc1, 24, rNone);
+ return res;
+ case OP_2SHORT:
+ res = opRegRegImm(cUnit, OP_LSL, rDestSrc1, rSrc2, 16, rNone);
+ opRegRegImm(cUnit, OP_ASR, rDestSrc1, rDestSrc1, 16, rNone);
+ return res;
+ case OP_2CHAR:
+ res = opRegRegImm(cUnit, OP_LSL, rDestSrc1, rSrc2, 16, rNone);
+ opRegRegImm(cUnit, OP_LSR, rDestSrc1, rDestSrc1, 16, rNone);
+ return res;
+ default:
+ assert(0);
+ break;
+ }
+ return newLIR2(cUnit, opCode, rDestSrc1, rSrc2);
+}
+
+static ArmLIR *opRegImm(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
+ int value, int rScratch)
+{
+ ArmLIR *res;
+ bool neg = (value < 0);
+ int absValue = (neg) ? -value : value;
+ bool shortForm = (absValue & 0xff) == absValue;
+ ArmOpCode opCode = THUMB_BKPT;
+ switch (op) {
+ case OP_ADD:
+ if ( !neg && (rDestSrc1 == 13) && (value <= 508)) { /* sp */
+ assert((value & 0x3) == 0);
+ return newLIR1(cUnit, THUMB_ADD_SPI7, value >> 2);
+ } else if (shortForm) {
+ opCode = (neg) ? THUMB_SUB_RI8 : THUMB_ADD_RI8;
+ } else
+ opCode = THUMB_ADD_RRR;
+ break;
+ case OP_SUB:
+ if (!neg && (rDestSrc1 == 13) && (value <= 508)) { /* sp */
+ assert((value & 0x3) == 0);
+ return newLIR1(cUnit, THUMB_SUB_SPI7, value >> 2);
+ } else if (shortForm) {
+ opCode = (neg) ? THUMB_ADD_RI8 : THUMB_SUB_RI8;
+ } else
+ opCode = THUMB_SUB_RRR;
+ break;
+ case OP_CMP:
+ if (LOWREG(rDestSrc1) && shortForm)
+ opCode = (shortForm) ? THUMB_CMP_RI8 : THUMB_CMP_RR;
+ else if (LOWREG(rDestSrc1))
+ opCode = THUMB_CMP_RR;
+ else {
+ shortForm = false;
+ opCode = THUMB_CMP_HL;
+ }
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ if (shortForm)
+ res = newLIR2(cUnit, opCode, rDestSrc1, absValue);
+ else {
+ assert(rScratch != rNone);
+ res = loadConstant(cUnit, rScratch, value);
+ newLIR3(cUnit, opCode, rDestSrc1, rDestSrc1, rScratch);
+ }
+ return res;
+}
+
+static ArmLIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest,
+ int rSrc1, int rSrc2)
+{
+ ArmOpCode opCode = THUMB_BKPT;
+ switch (op) {
+ case OP_ADD:
+ opCode = THUMB_ADD_RRR;
+ break;
+ case OP_SUB:
+ opCode = THUMB_SUB_RRR;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ return newLIR3(cUnit, opCode, rDest, rSrc1, rSrc2);
+}
+
+static ArmLIR *opRegRegImm(CompilationUnit *cUnit, OpKind op, int rDest,
+ int rSrc1, int value, int rScratch)
+{
+ ArmLIR *res;
+ bool neg = (value < 0);
+ int absValue = (neg) ? -value : value;
+ ArmOpCode opCode = THUMB_BKPT;
+ bool shortForm = (absValue & 0x7) == absValue;
+ switch(op) {
+ case OP_ADD:
+ if ((rSrc1 == 13) && (value <= 1020)) { /* sp */
+ assert((value & 0x3) == 0);
+ shortForm = true;
+ opCode = THUMB_ADD_SP_REL;
+ value >>= 2;
+ } else if ((rSrc1 == 15) && (value <= 1020)) { /* pc */
+ assert((value & 0x3) == 0);
+ shortForm = true;
+ opCode = THUMB_ADD_PC_REL;
+ value >>= 2;
+ } else if (shortForm) {
+ opCode = (neg) ? THUMB_SUB_RRI3 : THUMB_ADD_RRI3;
+ } else if ((absValue > 0) && (absValue <= (255 + 7))) {
+ /* Two shots - 1st handle the 7 */
+ opCode = (neg) ? THUMB_SUB_RRI3 : THUMB_ADD_RRI3;
+ res = newLIR3(cUnit, opCode, rDest, rSrc1, 7);
+ opCode = (neg) ? THUMB_SUB_RI8 : THUMB_ADD_RI8;
+ newLIR2(cUnit, opCode, rDest, absValue - 7);
+ return res;
+ } else
+ opCode = THUMB_ADD_RRR;
+ break;
+
+ case OP_SUB:
+ if (shortForm) {
+ opCode = (neg) ? THUMB_ADD_RRI3 : THUMB_SUB_RRI3;
+ } else if ((absValue > 0) && (absValue <= (255 + 7))) {
+ /* Two shots - 1st handle the 7 */
+ opCode = (neg) ? THUMB_ADD_RRI3 : THUMB_SUB_RRI3;
+ res = newLIR3(cUnit, opCode, rDest, rSrc1, 7);
+ opCode = (neg) ? THUMB_ADD_RI8 : THUMB_SUB_RI8;
+ newLIR2(cUnit, opCode, rDest, absValue - 7);
+ return res;
+ } else
+ opCode = THUMB_SUB_RRR;
+ break;
+ case OP_LSL:
+ shortForm = (!neg && value <= 31);
+ opCode = THUMB_LSL_RRI5;
+ break;
+ case OP_LSR:
+ shortForm = (!neg && value <= 31);
+ opCode = THUMB_LSR_RRI5;
+ break;
+ case OP_ASR:
+ shortForm = (!neg && value <= 31);
+ opCode = THUMB_ASR_RRI5;
+ break;
+ case OP_MUL:
+ case OP_AND:
+ case OP_OR:
+ case OP_XOR:
+ if (rDest == rSrc1) {
+ res = loadConstant(cUnit, rScratch, value);
+ opRegReg(cUnit, op, rDest, rScratch);
+ } else {
+ res = loadConstant(cUnit, rDest, value);
+ opRegReg(cUnit, op, rDest, rSrc1);
+ }
+ return res;
+ default:
+ assert(0);
+ break;
+ }
+ if (shortForm)
+ res = newLIR3(cUnit, opCode, rDest, rSrc1, absValue);
+ else {
+ if (rDest != rSrc1) {
+ res = loadConstant(cUnit, rDest, value);
+ newLIR3(cUnit, opCode, rDest, rSrc1, rDest);
+ } else {
+ assert(rScratch != rNone);
+ res = loadConstant(cUnit, rScratch, value);
+ newLIR3(cUnit, opCode, rDest, rSrc1, rScratch);
+ }
+ }
+ return res;
+}
+
+static void genCmpLong(CompilationUnit *cUnit, MIR *mir,
+ int vDest, int vSrc1, int vSrc2)
+{
+ loadValuePair(cUnit, vSrc1, r0, r1);
+ loadValuePair(cUnit, vSrc2, r2, r3);
+ genDispatchToHandler(cUnit, TEMPLATE_CMP_LONG);
+ storeValue(cUnit, r0, vDest, r1);
+}
+
+static bool genInlinedStringLength(CompilationUnit *cUnit, MIR *mir)
+{
+ DecodedInstruction *dInsn = &mir->dalvikInsn;
+ int offset = offsetof(InterpState, retval);
+ int regObj = selectFirstRegister(cUnit, dInsn->arg[0], false);
+ int reg1 = NEXT_REG(regObj);
+ loadValue(cUnit, dInsn->arg[0], regObj);
+ genNullCheck(cUnit, dInsn->arg[0], regObj, mir->offset, NULL);
+ loadWordDisp(cUnit, regObj, gDvm.offJavaLangString_count, reg1);
+ storeWordDisp(cUnit, rGLUE, offset, reg1, regObj);
+ return false;
+}
+
+static bool genInlinedStringCharAt(CompilationUnit *cUnit, MIR *mir)
+{
+ DecodedInstruction *dInsn = &mir->dalvikInsn;
+ int offset = offsetof(InterpState, retval);
+ int contents = offsetof(ArrayObject, contents);
+ int regObj = selectFirstRegister(cUnit, dInsn->arg[0], false);
+ int regIdx = NEXT_REG(regObj);
+ int regMax = NEXT_REG(regIdx);
+ int regOff = NEXT_REG(regMax);
+ loadValue(cUnit, dInsn->arg[0], regObj);
+ loadValue(cUnit, dInsn->arg[1], regIdx);
+ ArmLIR * pcrLabel = genNullCheck(cUnit, dInsn->arg[0], regObj,
+ mir->offset, NULL);
+ loadWordDisp(cUnit, regObj, gDvm.offJavaLangString_count, regMax);
+ loadWordDisp(cUnit, regObj, gDvm.offJavaLangString_offset, regOff);
+ loadWordDisp(cUnit, regObj, gDvm.offJavaLangString_value, regObj);
+ genBoundsCheck(cUnit, regIdx, regMax, mir->offset, pcrLabel);
+
+ newLIR2(cUnit, THUMB_ADD_RI8, regObj, contents);
+ newLIR3(cUnit, THUMB_ADD_RRR, regIdx, regIdx, regOff);
+ newLIR3(cUnit, THUMB_ADD_RRR, regIdx, regIdx, regIdx);
+ newLIR3(cUnit, THUMB_LDRH_RRR, regMax, regObj, regIdx);
+ storeWordDisp(cUnit, rGLUE, offset, regMax, regObj);
+ return false;
+}
+
+static bool genInlinedAbsInt(CompilationUnit *cUnit, MIR *mir)
+{
+ int offset = offsetof(InterpState, retval);
+ DecodedInstruction *dInsn = &mir->dalvikInsn;
+ int reg0 = selectFirstRegister(cUnit, dInsn->arg[0], false);
+ int sign = NEXT_REG(reg0);
+ /* abs(x) = y<=x>>31, (x+y)^y. Shorter in ARM/THUMB2, no skip in THUMB */
+ loadValue(cUnit, dInsn->arg[0], reg0);
+ newLIR3(cUnit, THUMB_ASR_RRI5, sign, reg0, 31);
+ newLIR3(cUnit, THUMB_ADD_RRR, reg0, reg0, sign);
+ newLIR2(cUnit, THUMB_EOR_RR, reg0, sign);
+ storeWordDisp(cUnit, rGLUE, offset, reg0, sign);
+ return false;
+}
+
+static bool genInlinedAbsFloat(CompilationUnit *cUnit, MIR *mir)
+{
+ int offset = offsetof(InterpState, retval);
+ DecodedInstruction *dInsn = &mir->dalvikInsn;
+ int reg0 = selectFirstRegister(cUnit, dInsn->arg[0], false);
+ int signMask = NEXT_REG(reg0);
+ loadValue(cUnit, dInsn->arg[0], reg0);
+ loadConstant(cUnit, signMask, 0x7fffffff);
+ newLIR2(cUnit, THUMB_AND_RR, reg0, signMask);
+ storeWordDisp(cUnit, rGLUE, offset, reg0, signMask);
+ return false;
+}
+
+static bool genInlinedAbsDouble(CompilationUnit *cUnit, MIR *mir)
+{
+ int offset = offsetof(InterpState, retval);
+ DecodedInstruction *dInsn = &mir->dalvikInsn;
+ int oplo = selectFirstRegister(cUnit, dInsn->arg[0], true);
+ int ophi = NEXT_REG(oplo);
+ int signMask = NEXT_REG(ophi);
+ loadValuePair(cUnit, dInsn->arg[0], oplo, ophi);
+ loadConstant(cUnit, signMask, 0x7fffffff);
+ storeWordDisp(cUnit, rGLUE, offset, oplo, ophi);
+ newLIR2(cUnit, THUMB_AND_RR, ophi, signMask);
+ storeWordDisp(cUnit, rGLUE, offset + 4, ophi, oplo);
+ return false;
+}
+
+ /* No select in thumb, so we need to branch. Thumb2 will do better */
+static bool genInlinedMinMaxInt(CompilationUnit *cUnit, MIR *mir, bool isMin)
+{
+ int offset = offsetof(InterpState, retval);
+ DecodedInstruction *dInsn = &mir->dalvikInsn;
+ int reg0 = selectFirstRegister(cUnit, dInsn->arg[0], false);
+ int reg1 = NEXT_REG(reg0);
+ loadValue(cUnit, dInsn->arg[0], reg0);
+ loadValue(cUnit, dInsn->arg[1], reg1);
+ newLIR2(cUnit, THUMB_CMP_RR, reg0, reg1);
+ ArmLIR *branch1 = newLIR2(cUnit, THUMB_B_COND, 2,
+ isMin ? ARM_COND_LT : ARM_COND_GT);
+ newLIR2(cUnit, THUMB_MOV_RR, reg0, reg1);
+ ArmLIR *target =
+ newLIR3(cUnit, THUMB_STR_RRI5, reg0, rGLUE, offset >> 2);
+ branch1->generic.target = (LIR *)target;
+ return false;
+}
+
+static bool genInlinedAbsLong(CompilationUnit *cUnit, MIR *mir)
+{
+ int offset = offsetof(InterpState, retval);
+ DecodedInstruction *dInsn = &mir->dalvikInsn;
+ int oplo = selectFirstRegister(cUnit, dInsn->arg[0], true);
+ int ophi = NEXT_REG(oplo);
+ int sign = NEXT_REG(ophi);
+ /* abs(x) = y<=x>>31, (x+y)^y. Shorter in ARM/THUMB2, no skip in THUMB */
+ loadValuePair(cUnit, dInsn->arg[0], oplo, ophi);
+ newLIR3(cUnit, THUMB_ASR_RRI5, sign, ophi, 31);
+ newLIR3(cUnit, THUMB_ADD_RRR, oplo, oplo, sign);
+ newLIR2(cUnit, THUMB_ADC_RR, ophi, sign);
+ newLIR2(cUnit, THUMB_EOR_RR, oplo, sign);
+ newLIR2(cUnit, THUMB_EOR_RR, ophi, sign);
+ storeWordDisp(cUnit, rGLUE, offset, oplo, sign);
+ storeWordDisp(cUnit, rGLUE, offset + 4, ophi, sign);
+ return false;
+}
diff --git a/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c b/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c
index 6c5b010..d07d96e 100644
--- a/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c
+++ b/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c
@@ -74,7 +74,7 @@
}
/* Architecture-specific initializations and checks go here */
-bool dvmCompilerArchInit(void)
+static bool compilerArchVariantInit(void)
{
/* First, declare dvmCompiler_TEMPLATE_XXX for each template */
#define JIT_TEMPLATE(X) extern void dvmCompiler_TEMPLATE_##X();
@@ -116,21 +116,12 @@
{
int offset = offsetof(InterpState, retval);
OpCode opCode = mir->dalvikInsn.opCode;
- int vSrc = mir->dalvikInsn.vA;
+ int vSrc = mir->dalvikInsn.arg[0];
loadValueAddress(cUnit, vSrc, r2);
genDispatchToHandler(cUnit, TEMPLATE_SQRT_DOUBLE_VFP);
newLIR3(cUnit, THUMB_STR_RRI5, r0, rGLUE, offset >> 2);
newLIR3(cUnit, THUMB_STR_RRI5, r1, rGLUE, (offset >> 2) + 1);
- return false;
-}
-
-static bool genInlineCos(CompilationUnit *cUnit, MIR *mir)
-{
- return false;
-}
-
-static bool genInlineSin(CompilationUnit *cUnit, MIR *mir)
-{
+ resetRegisterScoreboard(cUnit);
return false;
}
diff --git a/vm/compiler/codegen/arm/armv5te/ArchVariant.c b/vm/compiler/codegen/arm/armv5te/ArchVariant.c
index a1f2b00..b4a3848 100644
--- a/vm/compiler/codegen/arm/armv5te/ArchVariant.c
+++ b/vm/compiler/codegen/arm/armv5te/ArchVariant.c
@@ -74,7 +74,7 @@
}
/* Architecture-specific initializations and checks go here */
-bool dvmCompilerArchInit(void)
+static bool compilerArchVariantInit(void)
{
/* First, declare dvmCompiler_TEMPLATE_XXX for each template */
#define JIT_TEMPLATE(X) extern void dvmCompiler_TEMPLATE_##X();
@@ -117,16 +117,6 @@
return false; /* punt to C handler */
}
-static bool genInlineCos(CompilationUnit *cUnit, MIR *mir)
-{
- return false; /* punt to C handler */
-}
-
-static bool genInlineSin(CompilationUnit *cUnit, MIR *mir)
-{
- return false; /* punt to C handler */
-}
-
static bool genConversion(CompilationUnit *cUnit, MIR *mir)
{
return genConversionPortable(cUnit, mir);
diff --git a/vm/compiler/codegen/arm/armv7-a/ArchVariant.c b/vm/compiler/codegen/arm/armv7-a/ArchVariant.c
index 92097af..fba1e32 100644
--- a/vm/compiler/codegen/arm/armv7-a/ArchVariant.c
+++ b/vm/compiler/codegen/arm/armv7-a/ArchVariant.c
@@ -14,8 +14,8 @@
* limitations under the License.
*/
+#include <math.h> // for double sqrt(double)
-static void loadFloat(CompilationUnit *cUnit, int vSrc, int rDest);
/*
* This file is included by Codegen-armv5te-vfp.c, and implements architecture
@@ -77,7 +77,7 @@
}
/* Architecture-specific initializations and checks go here */
-bool dvmCompilerArchInit(void)
+static bool compilerArchVariantInit(void)
{
/* First, declare dvmCompiler_TEMPLATE_XXX for each template */
#define JIT_TEMPLATE(X) extern void dvmCompiler_TEMPLATE_##X();
@@ -118,25 +118,31 @@
static bool genInlineSqrt(CompilationUnit *cUnit, MIR *mir)
{
int offset = offsetof(InterpState, retval);
- int vSrc = mir->dalvikInsn.vA;
+ int vSrc = mir->dalvikInsn.arg[0];
+ int vDest = inlinedTarget(mir);
+ ArmLIR *branch;
+ ArmLIR *target;
+
loadDouble(cUnit, vSrc, dr1);
newLIR2(cUnit, THUMB2_VSQRTD, dr0, dr1);
- assert(offset & 0x3 == 0); /* Must be word aligned */
- assert(offset < 1024);
- newLIR3(cUnit, THUMB2_VSTRD, dr0, rGLUE, offset >> 2);
+ newLIR2(cUnit, THUMB2_VCMPD, dr0, dr0);
+ newLIR0(cUnit, THUMB2_FMSTAT);
+ branch = newLIR2(cUnit, THUMB_B_COND, 0, ARM_COND_EQ);
+ loadConstant(cUnit, r2, (int)sqrt);
+ newLIR3(cUnit, THUMB2_FMRRD, r0, r1, dr1);
+ newLIR1(cUnit, THUMB_BLX_R, r2);
+ newLIR3(cUnit, THUMB2_FMDRR, dr0, r0, r1);
+ ArmLIR *label = newLIR0(cUnit, ARM_PSEUDO_TARGET_LABEL);
+ label->defMask = ENCODE_ALL;
+ branch->generic.target = (LIR *)label;
+ if (vDest >= 0)
+ storeDouble(cUnit, dr0, vDest);
+ else
+ newLIR3(cUnit, THUMB2_VSTRD, dr0, rGLUE, offset >> 2);
+ resetRegisterScoreboard(cUnit);
return true;
}
-static bool genInlineCos(CompilationUnit *cUnit, MIR *mir)
-{
- return false;
-}
-
-static bool genInlineSin(CompilationUnit *cUnit, MIR *mir)
-{
- return false;
-}
-
static bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir, int vDest,
int vSrc1, int vSrc2)
{
@@ -171,10 +177,21 @@
default:
return true;
}
- loadFloat(cUnit, vSrc1, fr2);
- loadFloat(cUnit, vSrc2, fr4);
- newLIR3(cUnit, op, fr0, fr2, fr4);
- storeFloat(cUnit, fr0, vDest, 0);
+ int reg0, reg1, reg2;
+ reg1 = selectSFPReg(cUnit, vSrc1);
+ reg2 = selectSFPReg(cUnit, vSrc2);
+ /*
+ * The register mapping is overly optimistic and lazily updated so we
+ * need to detect false sharing here.
+ */
+ if (reg1 == reg2 && vSrc1 != vSrc2) {
+ reg2 = nextFPReg(cUnit, vSrc2, false /* isDouble */);
+ }
+ loadFloat(cUnit, vSrc1, reg1);
+ loadFloat(cUnit, vSrc2, reg2);
+ reg0 = selectSFPReg(cUnit, vDest);
+ newLIR3(cUnit, op, reg0, reg1, reg2);
+ storeFloat(cUnit, reg0, vDest);
return false;
}
@@ -183,10 +200,6 @@
{
int op = THUMB_BKPT;
- /*
- * Don't attempt to optimize register usage since these opcodes call out to
- * the handlers.
- */
switch (mir->dalvikInsn.opCode) {
case OP_ADD_DOUBLE_2ADDR:
case OP_ADD_DOUBLE:
@@ -212,10 +225,19 @@
default:
return true;
}
- loadDouble(cUnit, vSrc1, dr1);
- loadDouble(cUnit, vSrc2, dr2);
- newLIR3(cUnit, op, dr0, dr1, dr2);
- storeDouble(cUnit, dr0, vDest, 0);
+
+ int reg0, reg1, reg2;
+ reg1 = selectDFPReg(cUnit, vSrc1);
+ reg2 = selectDFPReg(cUnit, vSrc2);
+ if (reg1 == reg2 && vSrc1 != vSrc2) {
+ reg2 = nextFPReg(cUnit, vSrc2, true /* isDouble */);
+ }
+ loadDouble(cUnit, vSrc1, reg1);
+ loadDouble(cUnit, vSrc2, reg2);
+ /* Rename the new vDest to a new register */
+ reg0 = selectDFPReg(cUnit, vNone);
+ newLIR3(cUnit, op, reg0, reg1, reg2);
+ storeDouble(cUnit, reg0, vDest);
return false;
}
@@ -270,18 +292,20 @@
return true;
}
if (longSrc) {
- srcReg = dr1;
+ srcReg = selectDFPReg(cUnit, vSrc2);
loadDouble(cUnit, vSrc2, srcReg);
} else {
- srcReg = fr2;
+ srcReg = selectSFPReg(cUnit, vSrc2);
loadFloat(cUnit, vSrc2, srcReg);
}
if (longDest) {
- newLIR2(cUnit, op, dr0, srcReg);
- storeDouble(cUnit, dr0, vSrc1Dest, 0);
+ int destReg = selectDFPReg(cUnit, vNone);
+ newLIR2(cUnit, op, destReg, srcReg);
+ storeDouble(cUnit, destReg, vSrc1Dest);
} else {
- newLIR2(cUnit, op, fr0, srcReg);
- storeFloat(cUnit, fr0, vSrc1Dest, 0);
+ int destReg = selectSFPReg(cUnit, vNone);
+ newLIR2(cUnit, op, destReg, srcReg);
+ storeFloat(cUnit, destReg, vSrc1Dest);
}
return false;
}
@@ -289,31 +313,61 @@
static bool genCmpX(CompilationUnit *cUnit, MIR *mir, int vDest, int vSrc1,
int vSrc2)
{
- TemplateOpCode template;
+ bool isDouble;
+ int defaultResult;
+ bool ltNaNBias;
+ int fpReg1, fpReg2;
- /*
- * Don't attempt to optimize register usage since these opcodes call out to
- * the handlers.
- */
switch(mir->dalvikInsn.opCode) {
case OP_CMPL_FLOAT:
- template = TEMPLATE_CMPL_FLOAT_VFP;
+ isDouble = false;
+ defaultResult = -1;
break;
case OP_CMPG_FLOAT:
- template = TEMPLATE_CMPG_FLOAT_VFP;
+ isDouble = false;
+ defaultResult = 1;
break;
case OP_CMPL_DOUBLE:
- template = TEMPLATE_CMPL_DOUBLE_VFP;
+ isDouble = true;
+ defaultResult = -1;
break;
case OP_CMPG_DOUBLE:
- template = TEMPLATE_CMPG_DOUBLE_VFP;
+ isDouble = true;
+ defaultResult = 1;
break;
default:
return true;
}
- loadValueAddress(cUnit, vSrc1, r0);
- loadValueAddress(cUnit, vSrc2, r1);
- genDispatchToHandler(cUnit, template);
- storeValue(cUnit, r0, vDest, r1);
+ if (isDouble) {
+ fpReg1 = selectDFPReg(cUnit, vSrc1);
+ fpReg2 = selectDFPReg(cUnit, vSrc2);
+ if (fpReg1 == fpReg2 && vSrc1 != vSrc2) {
+ fpReg2 = nextFPReg(cUnit, vSrc2, true /* isDouble */);
+ }
+ loadDouble(cUnit, vSrc1, fpReg1);
+ loadDouble(cUnit, vSrc2, fpReg2);
+ // Hard-coded use of r7 as temp. Revisit
+ loadConstant(cUnit, r7, defaultResult);
+ newLIR2(cUnit, THUMB2_VCMPD, fpReg1, fpReg2);
+ } else {
+ fpReg1 = selectSFPReg(cUnit, vSrc1);
+ fpReg2 = selectSFPReg(cUnit, vSrc2);
+ if (fpReg1 == fpReg2 && vSrc1 != vSrc2) {
+ fpReg2 = nextFPReg(cUnit, vSrc2, false /* isDouble */);
+ }
+ loadFloat(cUnit, vSrc1, fpReg1);
+ loadFloat(cUnit, vSrc2, fpReg2);
+ // Hard-coded use of r7 as temp. Revisit
+ loadConstant(cUnit, r7, defaultResult);
+ newLIR2(cUnit, THUMB2_VCMPS, fpReg1, fpReg2);
+ }
+ newLIR0(cUnit, THUMB2_FMSTAT);
+ genIT(cUnit, (defaultResult == -1) ? ARM_COND_GT : ARM_COND_MI, "");
+ newLIR2(cUnit, THUMB2_MOV_IMM_SHIFT, r7,
+ modifiedImmediate(-defaultResult)); // Must not alter ccodes
+ genIT(cUnit, ARM_COND_EQ, "");
+ loadConstant(cUnit, r7, 0);
+ // Hard-coded use of r4PC as temp. Revisit
+ storeValue(cUnit, r7, vDest, r4PC);
return false;
}
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S
index 3801f49..1b143a9 100644
--- a/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S
@@ -25,7 +25,7 @@
/* op vAA, vBB, vCC */
fldd d0, [r0] @ d0<- vBB
fldd d1, [r1] @ d1<- vCC
- fcmped d0, d1 @ compare (vBB, vCC)
+ fcmpd d0, d1 @ compare (vBB, vCC)
mov r0, #1 @ r0<- 1 (default)
fmstat @ export status flags
mvnmi r0, #0 @ (less than) r0<- -1
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S
index 1faafa1..0510ef6 100644
--- a/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S
@@ -24,7 +24,7 @@
/* op vAA, vBB, vCC */
flds s0, [r0] @ d0<- vBB
flds s1, [r1] @ d1<- vCC
- fcmpes s0, s1 @ compare (vBB, vCC)
+ fcmps s0, s1 @ compare (vBB, vCC)
mov r0, #1 @ r0<- 1 (default)
fmstat @ export status flags
mvnmi r0, #0 @ (less than) r0<- -1
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S
index 014f160..bdb42d6 100644
--- a/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S
@@ -24,7 +24,7 @@
/* op vAA, vBB, vCC */
flds s0, [r0] @ d0<- vBB
flds s1, [r1] @ d1<- vCC
- fcmpes s0, s1 @ compare (vBB, vCC)
+ fcmps s0, s1 @ compare (vBB, vCC)
mvn r0, #0 @ r0<- -1 (default)
fmstat @ export status flags
movgt r0, #1 @ (greater than) r0<- 1
diff --git a/vm/compiler/template/armv5te-vfp/TemplateOpList.h b/vm/compiler/template/armv5te-vfp/TemplateOpList.h
index c95163c..6d1ce67 100644
--- a/vm/compiler/template/armv5te-vfp/TemplateOpList.h
+++ b/vm/compiler/template/armv5te-vfp/TemplateOpList.h
@@ -50,3 +50,4 @@
JIT_TEMPLATE(CMPG_FLOAT_VFP)
JIT_TEMPLATE(CMPL_FLOAT_VFP)
JIT_TEMPLATE(SQRT_DOUBLE_VFP)
+JIT_TEMPLATE(THROW_EXCEPTION_COMMON)
diff --git a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S
index b20d564..8d31807 100644
--- a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S
+++ b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S
@@ -22,7 +22,11 @@
str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
cmp r8, #0 @ suspendCount != 0
ldr r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
+#if !defined(WITH_SELF_VERIFICATION)
bxne lr @ bail to the interpreter
+#else
+ bx lr @ bail to interpreter unconditionally
+#endif
@ go ahead and transfer control to the native code
ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
diff --git a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S
index 0ac7cf8..ec37bf9 100644
--- a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S
+++ b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S
@@ -31,7 +31,11 @@
cmp r8, #0 @ suspendCount != 0
bxne lr @ bail to the interpreter
tst r10, #ACC_NATIVE
+#if !defined(WITH_SELF_VERIFICATION)
bne .LinvokeNative
+#else
+ bxne lr @ bail to the interpreter
+#endif
ldr r10, .LdvmJitToInterpNoChain
ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
diff --git a/vm/compiler/template/armv5te/TEMPLATE_RETURN.S b/vm/compiler/template/armv5te/TEMPLATE_RETURN.S
index f0a4623..1e4aad2 100644
--- a/vm/compiler/template/armv5te/TEMPLATE_RETURN.S
+++ b/vm/compiler/template/armv5te/TEMPLATE_RETURN.S
@@ -9,12 +9,20 @@
ldr r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
ldr rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
+#if !defined(WITH_SELF_VERIFICATION)
ldr r9, [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
+#else
+ mov r9, #0 @ disable chaining
+#endif
ldr r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)]
@ r2<- method we're returning to
ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
cmp r2, #0 @ break frame?
+#if !defined(WITH_SELF_VERIFICATION)
beq 1f @ bail to interpreter
+#else
+ blxeq lr @ punt to interpreter and compare state
+#endif
ldr r0, .LdvmJitToInterpNoChain @ defined in footer.S
mov rFP, r10 @ publish new FP
ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz
diff --git a/vm/compiler/template/armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S b/vm/compiler/template/armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S
new file mode 100644
index 0000000..b737798
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S
@@ -0,0 +1,6 @@
+ /*
+ * Throw an exception from JIT'ed code.
+ * On entry:
+ * r0 Dalvik PC that raises the exception
+ */
+ b .LhandleException
diff --git a/vm/compiler/template/armv5te/TemplateOpList.h b/vm/compiler/template/armv5te/TemplateOpList.h
index 39cd07a..20fb7fa 100644
--- a/vm/compiler/template/armv5te/TemplateOpList.h
+++ b/vm/compiler/template/armv5te/TemplateOpList.h
@@ -35,3 +35,4 @@
JIT_TEMPLATE(SHL_LONG)
JIT_TEMPLATE(SHR_LONG)
JIT_TEMPLATE(USHR_LONG)
+JIT_TEMPLATE(THROW_EXCEPTION_COMMON)
diff --git a/vm/compiler/template/armv5te/footer.S b/vm/compiler/template/armv5te/footer.S
index 3b0b149..c373250 100644
--- a/vm/compiler/template/armv5te/footer.S
+++ b/vm/compiler/template/armv5te/footer.S
@@ -31,15 +31,19 @@
str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp
cmp r1, #0 @ null?
str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+ ldr r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
bne .LhandleException @ no, handle exception
bx r2
-/* NOTE - this path can be exercised if the JIT threshold is set to 5 */
+/*
+ * On entry:
+ * r0 Faulting Dalvik PC
+ */
.LhandleException:
- ldr r0, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
+ ldr r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
ldr rIBASE, .LdvmAsmInstructionStart @ same as above
- ldr rPC, [r10, #offStackSaveArea_savedPc] @ reload rPC
- mov pc, r0 @ branch to dvmMterpCommonExceptionThrown
+ mov rPC, r0 @ reload the faulting Dalvik address
+ mov pc, r1 @ branch to dvmMterpCommonExceptionThrown
.align 2
.LdvmAsmInstructionStart:
diff --git a/vm/compiler/template/armv7-a/TemplateOpList.h b/vm/compiler/template/armv7-a/TemplateOpList.h
index c95163c..6d1ce67 100644
--- a/vm/compiler/template/armv7-a/TemplateOpList.h
+++ b/vm/compiler/template/armv7-a/TemplateOpList.h
@@ -50,3 +50,4 @@
JIT_TEMPLATE(CMPG_FLOAT_VFP)
JIT_TEMPLATE(CMPL_FLOAT_VFP)
JIT_TEMPLATE(SQRT_DOUBLE_VFP)
+JIT_TEMPLATE(THROW_EXCEPTION_COMMON)
diff --git a/vm/compiler/template/config-armv5te-vfp b/vm/compiler/template/config-armv5te-vfp
index 628e75f..ab3ff90 100644
--- a/vm/compiler/template/config-armv5te-vfp
+++ b/vm/compiler/template/config-armv5te-vfp
@@ -42,6 +42,7 @@
op TEMPLATE_SHL_LONG armv5te
op TEMPLATE_SHR_LONG armv5te
op TEMPLATE_USHR_LONG armv5te
+ op TEMPLATE_THROW_EXCEPTION_COMMON armv5te
op-end
diff --git a/vm/compiler/template/config-armv7-a b/vm/compiler/template/config-armv7-a
index ecf0b3a..aed0fa7 100644
--- a/vm/compiler/template/config-armv7-a
+++ b/vm/compiler/template/config-armv7-a
@@ -42,6 +42,7 @@
op TEMPLATE_SHL_LONG armv5te
op TEMPLATE_SHR_LONG armv5te
op TEMPLATE_USHR_LONG armv5te
+ op TEMPLATE_THROW_EXCEPTION_COMMON armv5te
op-end
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S b/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
index 0c433a1..74d6936 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
@@ -180,12 +180,20 @@
ldr r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
ldr rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
+#if !defined(WITH_SELF_VERIFICATION)
ldr r9, [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
+#else
+ mov r9, #0 @ disable chaining
+#endif
ldr r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)]
@ r2<- method we're returning to
ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
cmp r2, #0 @ break frame?
+#if !defined(WITH_SELF_VERIFICATION)
beq 1f @ bail to interpreter
+#else
+ blxeq lr @ punt to interpreter and compare state
+#endif
ldr r0, .LdvmJitToInterpNoChain @ defined in footer.S
mov rFP, r10 @ publish new FP
ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz
@@ -246,7 +254,11 @@
cmp r8, #0 @ suspendCount != 0
bxne lr @ bail to the interpreter
tst r10, #ACC_NATIVE
+#if !defined(WITH_SELF_VERIFICATION)
bne .LinvokeNative
+#else
+ bxne lr @ bail to the interpreter
+#endif
ldr r10, .LdvmJitToInterpNoChain
ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
@@ -391,7 +403,11 @@
str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
cmp r8, #0 @ suspendCount != 0
ldr r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
+#if !defined(WITH_SELF_VERIFICATION)
bxne lr @ bail to the interpreter
+#else
+ bx lr @ bail to interpreter unconditionally
+#endif
@ go ahead and transfer control to the native code
ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
@@ -860,7 +876,7 @@
/* op vAA, vBB, vCC */
fldd d0, [r0] @ d0<- vBB
fldd d1, [r1] @ d1<- vCC
- fcmped d0, d1 @ compare (vBB, vCC)
+ fcmpd d0, d1 @ compare (vBB, vCC)
mov r0, #1 @ r0<- 1 (default)
fmstat @ export status flags
mvnmi r0, #0 @ (less than) r0<- -1
@@ -929,7 +945,7 @@
/* op vAA, vBB, vCC */
flds s0, [r0] @ d0<- vBB
flds s1, [r1] @ d1<- vCC
- fcmpes s0, s1 @ compare (vBB, vCC)
+ fcmps s0, s1 @ compare (vBB, vCC)
mov r0, #1 @ r0<- 1 (default)
fmstat @ export status flags
mvnmi r0, #0 @ (less than) r0<- -1
@@ -963,7 +979,7 @@
/* op vAA, vBB, vCC */
flds s0, [r0] @ d0<- vBB
flds s1, [r1] @ d1<- vCC
- fcmpes s0, s1 @ compare (vBB, vCC)
+ fcmps s0, s1 @ compare (vBB, vCC)
mvn r0, #0 @ r0<- -1 (default)
fmstat @ export status flags
movgt r0, #1 @ (greater than) r0<- 1
@@ -998,6 +1014,18 @@
.Lsqrt:
.word sqrt
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON
+dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON:
+/* File: armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S */
+ /*
+ * Throw an exception from JIT'ed code.
+ * On entry:
+ * r0 Dalvik PC that raises the exception
+ */
+ b .LhandleException
+
.size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
/* File: armv5te/footer.S */
/*
@@ -1033,15 +1061,19 @@
str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp
cmp r1, #0 @ null?
str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+ ldr r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
bne .LhandleException @ no, handle exception
bx r2
-/* NOTE - this path can be exercised if the JIT threshold is set to 5 */
+/*
+ * On entry:
+ * r0 Faulting Dalvik PC
+ */
.LhandleException:
- ldr r0, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
+ ldr r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
ldr rIBASE, .LdvmAsmInstructionStart @ same as above
- ldr rPC, [r10, #offStackSaveArea_savedPc] @ reload rPC
- mov pc, r0 @ branch to dvmMterpCommonExceptionThrown
+ mov rPC, r0 @ reload the faulting Dalvik address
+ mov pc, r1 @ branch to dvmMterpCommonExceptionThrown
.align 2
.LdvmAsmInstructionStart:
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S b/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
index 29dde74..d2e6f54 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
@@ -180,12 +180,20 @@
ldr r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
ldr rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
+#if !defined(WITH_SELF_VERIFICATION)
ldr r9, [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
+#else
+ mov r9, #0 @ disable chaining
+#endif
ldr r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)]
@ r2<- method we're returning to
ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
cmp r2, #0 @ break frame?
+#if !defined(WITH_SELF_VERIFICATION)
beq 1f @ bail to interpreter
+#else
+ blxeq lr @ punt to interpreter and compare state
+#endif
ldr r0, .LdvmJitToInterpNoChain @ defined in footer.S
mov rFP, r10 @ publish new FP
ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz
@@ -246,7 +254,11 @@
cmp r8, #0 @ suspendCount != 0
bxne lr @ bail to the interpreter
tst r10, #ACC_NATIVE
+#if !defined(WITH_SELF_VERIFICATION)
bne .LinvokeNative
+#else
+ bxne lr @ bail to the interpreter
+#endif
ldr r10, .LdvmJitToInterpNoChain
ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
@@ -391,7 +403,11 @@
str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
cmp r8, #0 @ suspendCount != 0
ldr r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
+#if !defined(WITH_SELF_VERIFICATION)
bxne lr @ bail to the interpreter
+#else
+ bx lr @ bail to interpreter unconditionally
+#endif
@ go ahead and transfer control to the native code
ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
@@ -732,6 +748,18 @@
bx lr
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON
+dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON:
+/* File: armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S */
+ /*
+ * Throw an exception from JIT'ed code.
+ * On entry:
+ * r0 Dalvik PC that raises the exception
+ */
+ b .LhandleException
+
.size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
/* File: armv5te/footer.S */
/*
@@ -767,15 +795,19 @@
str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp
cmp r1, #0 @ null?
str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+ ldr r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
bne .LhandleException @ no, handle exception
bx r2
-/* NOTE - this path can be exercised if the JIT threshold is set to 5 */
+/*
+ * On entry:
+ * r0 Faulting Dalvik PC
+ */
.LhandleException:
- ldr r0, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
+ ldr r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
ldr rIBASE, .LdvmAsmInstructionStart @ same as above
- ldr rPC, [r10, #offStackSaveArea_savedPc] @ reload rPC
- mov pc, r0 @ branch to dvmMterpCommonExceptionThrown
+ mov rPC, r0 @ reload the faulting Dalvik address
+ mov pc, r1 @ branch to dvmMterpCommonExceptionThrown
.align 2
.LdvmAsmInstructionStart:
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
index 9e97b74..4ed5ea1 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
@@ -180,12 +180,20 @@
ldr r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
ldr r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
ldr rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
+#if !defined(WITH_SELF_VERIFICATION)
ldr r9, [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
+#else
+ mov r9, #0 @ disable chaining
+#endif
ldr r2, [r10, #(offStackSaveArea_method - sizeofStackSaveArea)]
@ r2<- method we're returning to
ldr r3, [rGLUE, #offGlue_self] @ r3<- glue->self
cmp r2, #0 @ break frame?
+#if !defined(WITH_SELF_VERIFICATION)
beq 1f @ bail to interpreter
+#else
+ blxeq lr @ punt to interpreter and compare state
+#endif
ldr r0, .LdvmJitToInterpNoChain @ defined in footer.S
mov rFP, r10 @ publish new FP
ldrne r10, [r2, #offMethod_clazz] @ r10<- method->clazz
@@ -246,7 +254,11 @@
cmp r8, #0 @ suspendCount != 0
bxne lr @ bail to the interpreter
tst r10, #ACC_NATIVE
+#if !defined(WITH_SELF_VERIFICATION)
bne .LinvokeNative
+#else
+ bxne lr @ bail to the interpreter
+#endif
ldr r10, .LdvmJitToInterpNoChain
ldr r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
@@ -391,7 +403,11 @@
str r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
cmp r8, #0 @ suspendCount != 0
ldr r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
+#if !defined(WITH_SELF_VERIFICATION)
bxne lr @ bail to the interpreter
+#else
+ bx lr @ bail to interpreter unconditionally
+#endif
@ go ahead and transfer control to the native code
ldr r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
@@ -860,7 +876,7 @@
/* op vAA, vBB, vCC */
fldd d0, [r0] @ d0<- vBB
fldd d1, [r1] @ d1<- vCC
- fcmped d0, d1 @ compare (vBB, vCC)
+ fcmpd d0, d1 @ compare (vBB, vCC)
mov r0, #1 @ r0<- 1 (default)
fmstat @ export status flags
mvnmi r0, #0 @ (less than) r0<- -1
@@ -929,7 +945,7 @@
/* op vAA, vBB, vCC */
flds s0, [r0] @ d0<- vBB
flds s1, [r1] @ d1<- vCC
- fcmpes s0, s1 @ compare (vBB, vCC)
+ fcmps s0, s1 @ compare (vBB, vCC)
mov r0, #1 @ r0<- 1 (default)
fmstat @ export status flags
mvnmi r0, #0 @ (less than) r0<- -1
@@ -963,7 +979,7 @@
/* op vAA, vBB, vCC */
flds s0, [r0] @ d0<- vBB
flds s1, [r1] @ d1<- vCC
- fcmpes s0, s1 @ compare (vBB, vCC)
+ fcmps s0, s1 @ compare (vBB, vCC)
mvn r0, #0 @ r0<- -1 (default)
fmstat @ export status flags
movgt r0, #1 @ (greater than) r0<- 1
@@ -998,6 +1014,18 @@
.Lsqrt:
.word sqrt
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON
+dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON:
+/* File: armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S */
+ /*
+ * Throw an exception from JIT'ed code.
+ * On entry:
+ * r0 Dalvik PC that raises the exception
+ */
+ b .LhandleException
+
.size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
/* File: armv5te/footer.S */
/*
@@ -1033,15 +1061,19 @@
str rFP, [r9, #offThread_curFrame] @ self->curFrame = fp
cmp r1, #0 @ null?
str r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+ ldr r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
bne .LhandleException @ no, handle exception
bx r2
-/* NOTE - this path can be exercised if the JIT threshold is set to 5 */
+/*
+ * On entry:
+ * r0 Faulting Dalvik PC
+ */
.LhandleException:
- ldr r0, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
+ ldr r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
ldr rIBASE, .LdvmAsmInstructionStart @ same as above
- ldr rPC, [r10, #offStackSaveArea_savedPc] @ reload rPC
- mov pc, r0 @ branch to dvmMterpCommonExceptionThrown
+ mov rPC, r0 @ reload the faulting Dalvik address
+ mov pc, r1 @ branch to dvmMterpCommonExceptionThrown
.align 2
.LdvmAsmInstructionStart:
diff --git a/vm/interp/Interp.c b/vm/interp/Interp.c
index 233ee3f..5a0e15f 100644
--- a/vm/interp/Interp.c
+++ b/vm/interp/Interp.c
@@ -897,6 +897,9 @@
extern void dvmJitToInterpSingleStep();
extern void dvmJitToTraceSelect();
extern void dvmJitToPatchPredictedChain();
+#if defined(WITH_SELF_VERIFICATION)
+ extern void dvmJitToBackwardBranch();
+#endif
/*
* Reserve a static entity here to quickly setup runtime contents as
@@ -909,6 +912,9 @@
dvmJitToInterpSingleStep,
dvmJitToTraceSelect,
dvmJitToPatchPredictedChain,
+#if defined(WITH_SELF_VERIFICATION)
+ dvmJitToBackwardBranch,
+#endif
};
#endif
diff --git a/vm/interp/InterpDefs.h b/vm/interp/InterpDefs.h
index c9c80e3..28994b7 100644
--- a/vm/interp/InterpDefs.h
+++ b/vm/interp/InterpDefs.h
@@ -38,6 +38,16 @@
} InterpEntry;
#if defined(WITH_JIT)
+#if defined(WITH_SELF_VERIFICATION)
+typedef struct HeapArgSpace {
+ int r0;
+ int r1;
+ int r2;
+ int r3;
+ int regMap;
+} HeapArgSpace;
+#endif
+
/*
* There are six entry points from the compiled code to the interpreter:
* 1) dvmJitToInterpNormal: find if there is a corresponding compilation for
@@ -64,6 +74,9 @@
* just been reached).
* 6) dvmJitToPredictedChain: patch the chaining cell for a virtual call site
* to a predicted callee.
+ * 7) dvmJitToBackwardBranch: (WITH_SELF_VERIFICATION ONLY) special case of 1)
+ * and 5). This is used instead if the ending branch of the trace jumps back
+ * into the same basic block.
*/
struct JitToInterpEntries {
void *dvmJitToInterpNormal;
@@ -72,6 +85,9 @@
void *dvmJitToInterpSingleStep;
void *dvmJitToTraceSelect;
void *dvmJitToPatchPredictedChain;
+#if defined(WITH_SELF_VERIFICATION)
+ void *dvmJitToBackwardBranch;
+#endif
};
#define JIT_TRACE_THRESH_FILTER_SIZE 16
@@ -145,10 +161,14 @@
int currTraceRun;
int totalTraceLen; // Number of Dalvik insts in trace
- const u2* currTraceHead; // Start of the trace we're building
- const u2* currRunHead; // Start of run we're building
+ const u2* currTraceHead; // Start of the trace we're building
+ const u2* currRunHead; // Start of run we're building
int currRunLen; // Length of run in 16-bit words
int lastThreshFilter;
+ const u2* lastPC; // Stage the PC first for the threaded interpreter
+#if defined(WITH_SELF_VERIFICATION)
+ struct HeapArgSpace heapArgSpace;
+#endif
const u2* threshFilter[JIT_TRACE_THRESH_FILTER_SIZE];
JitTraceRun trace[MAX_JIT_RUN_LEN];
#endif
diff --git a/vm/interp/Jit.c b/vm/interp/Jit.c
index 2bcb1f5..d8dcf1e 100644
--- a/vm/interp/Jit.c
+++ b/vm/interp/Jit.c
@@ -33,6 +33,302 @@
#include "compiler/CompilerIR.h"
#include <errno.h>
+#if defined(WITH_SELF_VERIFICATION)
+/* Allocate space for per-thread ShadowSpace data structures */
+void* dvmSelfVerificationShadowSpaceAlloc(Thread* self)
+{
+ self->shadowSpace = (ShadowSpace*) calloc(1, sizeof(ShadowSpace));
+ if (self->shadowSpace == NULL)
+ return NULL;
+
+ self->shadowSpace->registerSpaceSize = REG_SPACE;
+ self->shadowSpace->registerSpace =
+ (int*) calloc(self->shadowSpace->registerSpaceSize, sizeof(int));
+
+ return self->shadowSpace->registerSpace;
+}
+
+/* Free per-thread ShadowSpace data structures */
+void dvmSelfVerificationShadowSpaceFree(Thread* self)
+{
+ free(self->shadowSpace->registerSpace);
+ free(self->shadowSpace);
+}
+
+/*
+ * Save out PC, FP, InterpState, and registers to shadow space.
+ * Return a pointer to the shadow space for JIT to use.
+ */
+void* dvmSelfVerificationSaveState(const u2* pc, const void* fp,
+ void* interpStatePtr)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowSpace *shadowSpace = self->shadowSpace;
+ InterpState *interpState = (InterpState *) interpStatePtr;
+ int preBytes = interpState->method->outsSize*4 + sizeof(StackSaveArea);
+ int postBytes = interpState->method->registersSize*4;
+
+ //LOGD("### selfVerificationSaveState(%d) pc: 0x%x fp: 0x%x",
+ // self->threadId, (int)pc, (int)fp);
+
+ if (shadowSpace->selfVerificationState != kSVSIdle) {
+ LOGD("~~~ Save: INCORRECT PREVIOUS STATE(%d): %d",
+ self->threadId, shadowSpace->selfVerificationState);
+ LOGD("********** SHADOW STATE DUMP **********");
+ LOGD("* PC: 0x%x FP: 0x%x", (int)pc, (int)fp);
+ }
+ shadowSpace->selfVerificationState = kSVSStart;
+
+ // Dynamically grow shadow register space if necessary
+ while (preBytes + postBytes > shadowSpace->registerSpaceSize) {
+ shadowSpace->registerSpaceSize *= 2;
+ free(shadowSpace->registerSpace);
+ shadowSpace->registerSpace =
+ (int*) calloc(shadowSpace->registerSpaceSize, sizeof(int));
+ }
+
+ // Remember original state
+ shadowSpace->startPC = pc;
+ shadowSpace->fp = fp;
+ shadowSpace->glue = interpStatePtr;
+ shadowSpace->shadowFP = shadowSpace->registerSpace +
+ shadowSpace->registerSpaceSize - postBytes/4;
+
+ // Create a copy of the InterpState
+ memcpy(&(shadowSpace->interpState), interpStatePtr, sizeof(InterpState));
+ shadowSpace->interpState.fp = shadowSpace->shadowFP;
+ shadowSpace->interpState.interpStackEnd = (u1*)shadowSpace->registerSpace;
+
+ // Create a copy of the stack
+ memcpy(((char*)shadowSpace->shadowFP)-preBytes, ((char*)fp)-preBytes,
+ preBytes+postBytes);
+
+ // Setup the shadowed heap space
+ shadowSpace->heapSpaceTail = shadowSpace->heapSpace;
+
+ // Reset trace length
+ shadowSpace->traceLength = 0;
+
+ return shadowSpace;
+}
+
+/*
+ * Save ending PC, FP and compiled code exit point to shadow space.
+ * Return a pointer to the shadow space for JIT to restore state.
+ */
+void* dvmSelfVerificationRestoreState(const u2* pc, const void* fp,
+ SelfVerificationState exitPoint)
+{
+ Thread *self = dvmThreadSelf();
+ ShadowSpace *shadowSpace = self->shadowSpace;
+ shadowSpace->endPC = pc;
+ shadowSpace->endShadowFP = fp;
+
+ //LOGD("### selfVerificationRestoreState(%d) pc: 0x%x fp: 0x%x endPC: 0x%x",
+ // self->threadId, (int)shadowSpace->startPC, (int)shadowSpace->fp,
+ // (int)pc);
+
+ if (shadowSpace->selfVerificationState != kSVSStart) {
+ LOGD("~~~ Restore: INCORRECT PREVIOUS STATE(%d): %d",
+ self->threadId, shadowSpace->selfVerificationState);
+ LOGD("********** SHADOW STATE DUMP **********");
+ LOGD("* Dalvik PC: 0x%x endPC: 0x%x", (int)shadowSpace->startPC,
+ (int)shadowSpace->endPC);
+ LOGD("* Interp FP: 0x%x", (int)shadowSpace->fp);
+ LOGD("* Shadow FP: 0x%x endFP: 0x%x", (int)shadowSpace->shadowFP,
+ (int)shadowSpace->endShadowFP);
+ }
+
+ // Special case when punting after a single instruction
+ if (exitPoint == kSVSPunt && pc == shadowSpace->startPC) {
+ shadowSpace->selfVerificationState = kSVSIdle;
+ } else {
+ shadowSpace->selfVerificationState = exitPoint;
+ }
+
+ return shadowSpace;
+}
+
+/* Print contents of virtual registers */
+static void selfVerificationPrintRegisters(int* addr, int numWords)
+{
+ int i;
+ for (i = 0; i < numWords; i++) {
+ LOGD("* 0x%x: (v%d) 0x%8x", (int)(addr+i), i, *(addr+i));
+ }
+}
+
+/* Print values maintained in shadowSpace */
+static void selfVerificationDumpState(const u2* pc, Thread* self)
+{
+ ShadowSpace* shadowSpace = self->shadowSpace;
+ StackSaveArea* stackSave = SAVEAREA_FROM_FP(self->curFrame);
+ int frameBytes = (int) shadowSpace->registerSpace +
+ shadowSpace->registerSpaceSize*4 -
+ (int) shadowSpace->shadowFP;
+ int localRegs = 0;
+ int frameBytes2 = 0;
+ if (self->curFrame < shadowSpace->fp) {
+ localRegs = (stackSave->method->registersSize -
+ stackSave->method->insSize)*4;
+ frameBytes2 = (int) shadowSpace->fp - (int) self->curFrame - localRegs;
+ }
+ LOGD("********** SHADOW STATE DUMP **********");
+ LOGD("* CurrentPC: 0x%x, Offset: 0x%04x", (int)pc,
+ (int)(pc - stackSave->method->insns));
+ LOGD("* Class: %s Method: %s", stackSave->method->clazz->descriptor,
+ stackSave->method->name);
+ LOGD("* Dalvik PC: 0x%x endPC: 0x%x", (int)shadowSpace->startPC,
+ (int)shadowSpace->endPC);
+ LOGD("* Interp FP: 0x%x endFP: 0x%x", (int)shadowSpace->fp,
+ (int)self->curFrame);
+ LOGD("* Shadow FP: 0x%x endFP: 0x%x", (int)shadowSpace->shadowFP,
+ (int)shadowSpace->endShadowFP);
+ LOGD("* Frame1 Bytes: %d Frame2 Local: %d Bytes: %d", frameBytes,
+ localRegs, frameBytes2);
+ LOGD("* Trace length: %d State: %d", shadowSpace->traceLength,
+ shadowSpace->selfVerificationState);
+}
+
+/* Print decoded instructions in the current trace */
+static void selfVerificationDumpTrace(const u2* pc, Thread* self)
+{
+ ShadowSpace* shadowSpace = self->shadowSpace;
+ StackSaveArea* stackSave = SAVEAREA_FROM_FP(self->curFrame);
+ int i, addr, offset;
+ DecodedInstruction *decInsn;
+
+ LOGD("********** SHADOW TRACE DUMP **********");
+ for (i = 0; i < shadowSpace->traceLength; i++) {
+ addr = shadowSpace->trace[i].addr;
+ offset = (int)((u2*)addr - stackSave->method->insns);
+ decInsn = &(shadowSpace->trace[i].decInsn);
+ /* Not properly decoding instruction, some registers may be garbage */
+ LOGD("* 0x%x: (0x%04x) %s v%d, v%d, v%d", addr, offset,
+ getOpcodeName(decInsn->opCode), decInsn->vA, decInsn->vB,
+ decInsn->vC);
+ }
+}
+
+/* Code is forced into this spin loop when a divergence is detected */
+static void selfVerificationSpinLoop()
+{
+ gDvmJit.selfVerificationSpin = true;
+ while(gDvmJit.selfVerificationSpin) sleep(10);
+}
+
+/* Manage self verification while in the debug interpreter */
+static bool selfVerificationDebugInterp(const u2* pc, Thread* self)
+{
+ ShadowSpace *shadowSpace = self->shadowSpace;
+ SelfVerificationState state = shadowSpace->selfVerificationState;
+
+ DecodedInstruction decInsn;
+ dexDecodeInstruction(gDvm.instrFormat, pc, &decInsn);
+
+ //LOGD("### DbgIntp(%d): PC: 0x%x endPC: 0x%x state: %d len: %d %s",
+ // self->threadId, (int)pc, (int)shadowSpace->endPC, state,
+ // shadowSpace->traceLength, getOpcodeName(decInsn.opCode));
+
+ if (state == kSVSIdle || state == kSVSStart) {
+ LOGD("~~~ DbgIntrp: INCORRECT PREVIOUS STATE(%d): %d",
+ self->threadId, state);
+ selfVerificationDumpState(pc, self);
+ selfVerificationDumpTrace(pc, self);
+ }
+
+ /* Skip endPC once when trace has a backward branch */
+ if ((state == kSVSBackwardBranch && pc == shadowSpace->endPC) ||
+ state != kSVSBackwardBranch) {
+ shadowSpace->selfVerificationState = kSVSDebugInterp;
+ }
+
+ /* Check that the current pc is the end of the trace */
+ if ((state == kSVSSingleStep || state == kSVSDebugInterp) &&
+ pc == shadowSpace->endPC) {
+
+ shadowSpace->selfVerificationState = kSVSIdle;
+
+ /* Check register space */
+ int frameBytes = (int) shadowSpace->registerSpace +
+ shadowSpace->registerSpaceSize*4 -
+ (int) shadowSpace->shadowFP;
+ if (memcmp(shadowSpace->fp, shadowSpace->shadowFP, frameBytes)) {
+ LOGD("~~~ DbgIntp(%d): REGISTERS UNEQUAL!", self->threadId);
+ selfVerificationDumpState(pc, self);
+ selfVerificationDumpTrace(pc, self);
+ LOGD("*** Interp Registers: addr: 0x%x bytes: %d",
+ (int)shadowSpace->fp, frameBytes);
+ selfVerificationPrintRegisters((int*)shadowSpace->fp, frameBytes/4);
+ LOGD("*** Shadow Registers: addr: 0x%x bytes: %d",
+ (int)shadowSpace->shadowFP, frameBytes);
+ selfVerificationPrintRegisters((int*)shadowSpace->shadowFP,
+ frameBytes/4);
+ selfVerificationSpinLoop();
+ }
+ /* Check new frame if it exists (invokes only) */
+ if (self->curFrame < shadowSpace->fp) {
+ StackSaveArea* stackSave = SAVEAREA_FROM_FP(self->curFrame);
+ int localRegs = (stackSave->method->registersSize -
+ stackSave->method->insSize)*4;
+ int frameBytes2 = (int) shadowSpace->fp -
+ (int) self->curFrame - localRegs;
+ if (memcmp(((char*)self->curFrame)+localRegs,
+ ((char*)shadowSpace->endShadowFP)+localRegs, frameBytes2)) {
+ LOGD("~~~ DbgIntp(%d): REGISTERS (FRAME2) UNEQUAL!",
+ self->threadId);
+ selfVerificationDumpState(pc, self);
+ selfVerificationDumpTrace(pc, self);
+ LOGD("*** Interp Registers: addr: 0x%x l: %d bytes: %d",
+ (int)self->curFrame, localRegs, frameBytes2);
+ selfVerificationPrintRegisters((int*)self->curFrame,
+ (frameBytes2+localRegs)/4);
+ LOGD("*** Shadow Registers: addr: 0x%x l: %d bytes: %d",
+ (int)shadowSpace->endShadowFP, localRegs, frameBytes2);
+ selfVerificationPrintRegisters((int*)shadowSpace->endShadowFP,
+ (frameBytes2+localRegs)/4);
+ selfVerificationSpinLoop();
+ }
+ }
+
+ /* Check memory space */
+ bool memDiff = false;
+ ShadowHeap* heapSpacePtr;
+ for (heapSpacePtr = shadowSpace->heapSpace;
+ heapSpacePtr != shadowSpace->heapSpaceTail; heapSpacePtr++) {
+ int memData = *((unsigned int*) heapSpacePtr->addr);
+ if (heapSpacePtr->data != memData) {
+ LOGD("~~~ DbgIntp(%d): MEMORY UNEQUAL!", self->threadId);
+ LOGD("* Addr: 0x%x Intrp Data: 0x%x Jit Data: 0x%x",
+ heapSpacePtr->addr, memData, heapSpacePtr->data);
+ selfVerificationDumpState(pc, self);
+ selfVerificationDumpTrace(pc, self);
+ memDiff = true;
+ }
+ }
+ if (memDiff) selfVerificationSpinLoop();
+ return true;
+
+ /* If end not been reached, make sure max length not exceeded */
+ } else if (shadowSpace->traceLength >= JIT_MAX_TRACE_LEN) {
+ LOGD("~~~ DbgIntp(%d): CONTROL DIVERGENCE!", self->threadId);
+ LOGD("* startPC: 0x%x endPC: 0x%x currPC: 0x%x",
+ (int)shadowSpace->startPC, (int)shadowSpace->endPC, (int)pc);
+ selfVerificationDumpState(pc, self);
+ selfVerificationDumpTrace(pc, self);
+ selfVerificationSpinLoop();
+
+ return true;
+ }
+ /* Log the instruction address and decoded instruction for debug */
+ shadowSpace->trace[shadowSpace->traceLength].addr = (int)pc;
+ shadowSpace->trace[shadowSpace->traceLength].decInsn = decInsn;
+ shadowSpace->traceLength++;
+
+ return false;
+}
+#endif
+
int dvmJitStartup(void)
{
unsigned int i;
@@ -45,8 +341,9 @@
if (res && gDvm.executionMode == kExecutionModeJit) {
JitEntry *pJitTable = NULL;
unsigned char *pJitProfTable = NULL;
- assert(gDvm.jitTableSize &&
- !(gDvm.jitTableSize & (gDvmJit.jitTableSize - 1))); // Power of 2?
+ // Power of 2?
+ assert(gDvmJit.jitTableSize &&
+ !(gDvmJit.jitTableSize & (gDvmJit.jitTableSize - 1)));
dvmLockMutex(&gDvmJit.tableLock);
pJitTable = (JitEntry*)
calloc(gDvmJit.jitTableSize, sizeof(*pJitTable));
@@ -74,7 +371,7 @@
pJitTable[i].u.info.chain = gDvmJit.jitTableSize;
}
/* Is chain field wide enough for termination pattern? */
- assert(pJitTable[0].u.info.chain == gDvm.maxJitTableEntries);
+ assert(pJitTable[0].u.info.chain == gDvmJit.jitTableSize);
done:
gDvmJit.pJitEntryTable = pJitTable;
@@ -217,6 +514,9 @@
|| gDvm.activeProfilers
#endif
);
+ /* Prepare to handle last PC and stage the current PC */
+ const u2 *lastPC = interpState->lastPC;
+ interpState->lastPC = pc;
switch (interpState->jitState) {
char* nopStr;
@@ -224,19 +524,24 @@
int offset;
DecodedInstruction decInsn;
case kJitTSelect:
- dexDecodeInstruction(gDvm.instrFormat, pc, &decInsn);
+ /* First instruction - just remember the PC and exit */
+ if (lastPC == NULL) break;
+ /* Grow the trace around the last PC if jitState is kJitTSelect */
+ dexDecodeInstruction(gDvm.instrFormat, lastPC, &decInsn);
#if defined(SHOW_TRACE)
LOGD("TraceGen: adding %s",getOpcodeName(decInsn.opCode));
#endif
flags = dexGetInstrFlags(gDvm.instrFlags, decInsn.opCode);
- len = dexGetInstrOrTableWidthAbs(gDvm.instrWidth, pc);
- offset = pc - interpState->method->insns;
- if (pc != interpState->currRunHead + interpState->currRunLen) {
+ len = dexGetInstrOrTableWidthAbs(gDvm.instrWidth, lastPC);
+ offset = lastPC - interpState->method->insns;
+ assert((unsigned) offset <
+ dvmGetMethodInsnsSize(interpState->method));
+ if (lastPC != interpState->currRunHead + interpState->currRunLen) {
int currTraceRun;
/* We need to start a new trace run */
currTraceRun = ++interpState->currTraceRun;
interpState->currRunLen = 0;
- interpState->currRunHead = (u2*)pc;
+ interpState->currRunHead = (u2*)lastPC;
interpState->trace[currTraceRun].frag.startOffset = offset;
interpState->trace[currTraceRun].frag.numInsts = 0;
interpState->trace[currTraceRun].frag.runEnd = false;
@@ -245,6 +550,12 @@
interpState->trace[interpState->currTraceRun].frag.numInsts++;
interpState->totalTraceLen++;
interpState->currRunLen += len;
+
+ /* Will probably never hit this with the current trace buildier */
+ if (interpState->currTraceRun == (MAX_JIT_RUN_LEN - 1)) {
+ interpState->jitState = kJitTSelectEnd;
+ }
+
if ( ((flags & kInstrUnconditional) == 0) &&
/* don't end trace on INVOKE_DIRECT_EMPTY */
(decInsn.opCode != OP_INVOKE_DIRECT_EMPTY) &&
@@ -324,8 +635,23 @@
case kJitNormal:
switchInterp = !debugOrProfile;
break;
+#if defined(WITH_SELF_VERIFICATION)
+ case kJitSelfVerification:
+ if (selfVerificationDebugInterp(pc, self)) {
+ interpState->jitState = kJitNormal;
+ switchInterp = !debugOrProfile;
+ }
+ break;
+#endif
+ /* If JIT is off stay out of interpreter selections */
+ case kJitOff:
+ break;
default:
- dvmAbort();
+ if (!debugOrProfile) {
+ LOGE("Unexpected JIT state: %d", interpState->jitState);
+ dvmAbort();
+ }
+ break;
}
return switchInterp;
}
@@ -575,6 +901,7 @@
interpState->trace[0].frag.numInsts = 0;
interpState->trace[0].frag.runEnd = false;
interpState->trace[0].frag.hint = kJitHintNone;
+ interpState->lastPC = 0;
break;
case kJitTSelect:
case kJitTSelectAbort:
@@ -583,8 +910,12 @@
case kJitSingleStepEnd:
case kJitOff:
case kJitNormal:
+#if defined(WITH_SELF_VERIFICATION)
+ case kJitSelfVerification:
+#endif
break;
default:
+ LOGE("Unexpected JIT state: %d", interpState->jitState);
dvmAbort();
}
}
@@ -603,7 +934,7 @@
unsigned int oldSize;
unsigned int i;
- assert(gDvm.pJitEntryTable != NULL);
+ assert(gDvmJit.pJitEntryTable != NULL);
assert(size && !(size & (size - 1))); /* Is power of 2? */
LOGD("Jit: resizing JitTable from %d to %d", gDvmJit.jitTableSize, size);
diff --git a/vm/interp/Jit.h b/vm/interp/Jit.h
index 660b5ec..70931b8 100644
--- a/vm/interp/Jit.h
+++ b/vm/interp/Jit.h
@@ -25,6 +25,49 @@
#define JIT_MAX_TRACE_LEN 100
+#if defined (WITH_SELF_VERIFICATION)
+
+#define REG_SPACE 256 /* default size of shadow space */
+#define HEAP_SPACE JIT_MAX_TRACE_LEN /* default size of heap space */
+
+typedef struct ShadowHeap {
+ int addr;
+ int data;
+} ShadowHeap;
+
+typedef struct InstructionTrace {
+ int addr;
+ DecodedInstruction decInsn;
+} InstructionTrace;
+
+typedef struct ShadowSpace {
+ const u2* startPC; /* starting pc of jitted region */
+ const void* fp; /* starting fp of jitted region */
+ void* glue; /* starting glue ptr of jitted region */
+ SelfVerificationState selfVerificationState; /* self verification state */
+ const u2* endPC; /* ending pc of jitted region */
+ void* shadowFP; /* pointer to fp in shadow space */
+ InterpState interpState; /* copy of interpState */
+ int* registerSpace; /* copy of register state */
+ int registerSpaceSize; /* current size of register space */
+ ShadowHeap heapSpace[HEAP_SPACE]; /* copy of heap space */
+ ShadowHeap* heapSpaceTail; /* tail pointer to heapSpace */
+ const void* endShadowFP; /* ending fp in shadow space */
+ InstructionTrace trace[JIT_MAX_TRACE_LEN]; /* opcode trace for debugging */
+ int traceLength; /* counter for current trace length */
+} ShadowSpace;
+
+/*
+ * Self verification functions.
+ */
+void* dvmSelfVerificationShadowSpaceAlloc(Thread* self);
+void dvmSelfVerificationShadowSpaceFree(Thread* self);
+void* dvmSelfVerificationSaveState(const u2* pc, const void* fp,
+ void* interpStatePtr);
+void* dvmSelfVerificationRestoreState(const u2* pc, const void* fp,
+ SelfVerificationState exitPoint);
+#endif
+
/*
* JitTable hash function.
*/
diff --git a/vm/interp/Stack.c b/vm/interp/Stack.c
index 5920cbc..fe8ab26 100644
--- a/vm/interp/Stack.c
+++ b/vm/interp/Stack.c
@@ -80,7 +80,7 @@
"(req=%d top=%p cur=%p size=%d %s.%s)\n",
stackReq, self->interpStackStart, self->curFrame,
self->interpStackSize, method->clazz->descriptor, method->name);
- dvmHandleStackOverflow(self);
+ dvmHandleStackOverflow(self, method);
assert(dvmCheckException(self));
return false;
}
@@ -153,7 +153,7 @@
"(req=%d top=%p cur=%p size=%d '%s')\n",
stackReq, self->interpStackStart, self->curFrame,
self->interpStackSize, method->name);
- dvmHandleStackOverflow(self);
+ dvmHandleStackOverflow(self, method);
assert(dvmCheckException(self));
return false;
}
@@ -227,7 +227,7 @@
"(req=%d top=%p cur=%p size=%d '%s')\n",
stackReq, self->interpStackStart, self->curFrame,
self->interpStackSize, method->name);
- dvmHandleStackOverflow(self);
+ dvmHandleStackOverflow(self, method);
assert(dvmCheckException(self));
return false;
}
@@ -1014,7 +1014,7 @@
* need to resolve classes, which requires calling into the class loader if
* the classes aren't already in the "initiating loader" list.
*/
-void dvmHandleStackOverflow(Thread* self)
+void dvmHandleStackOverflow(Thread* self, const Method* method)
{
/*
* Can we make the reserved area available?
@@ -1030,7 +1030,15 @@
}
/* open it up to the full range */
- LOGI("Stack overflow, expanding (%p to %p)\n", self->interpStackEnd,
+ LOGI("threadid=%d: stack overflow on call to %s.%s:%s\n",
+ self->threadId,
+ method->clazz->descriptor, method->name, method->shorty);
+ StackSaveArea* saveArea = SAVEAREA_FROM_FP(self->curFrame);
+ LOGI(" method requires %d+%d+%d=%d bytes, fp is %p (%d left)\n",
+ method->registersSize * 4, sizeof(StackSaveArea), method->outsSize * 4,
+ (method->registersSize + method->outsSize) * 4 + sizeof(StackSaveArea),
+ saveArea, (u1*) saveArea - self->interpStackEnd);
+ LOGI(" expanding stack end (%p to %p)\n", self->interpStackEnd,
self->interpStackStart - self->interpStackSize);
//dvmDumpThread(self, false);
self->interpStackEnd = self->interpStackStart - self->interpStackSize;
diff --git a/vm/interp/Stack.h b/vm/interp/Stack.h
index 22f066f..208fe90 100644
--- a/vm/interp/Stack.h
+++ b/vm/interp/Stack.h
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
/*
* Stack frames, and uses thereof.
*/
@@ -275,7 +276,7 @@
/*
* Common handling for stack overflow.
*/
-void dvmHandleStackOverflow(Thread* self);
+void dvmHandleStackOverflow(Thread* self, const Method* method);
void dvmCleanupStackOverflow(Thread* self);
/* debugging; dvmDumpThread() is probably a better starting point */
diff --git a/vm/jdwp/JdwpHandler.c b/vm/jdwp/JdwpHandler.c
index ff6ecf4..53b5d26 100644
--- a/vm/jdwp/JdwpHandler.c
+++ b/vm/jdwp/JdwpHandler.c
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
/*
* Handle messages from debugger.
*
@@ -31,6 +32,7 @@
#include "Bits.h"
#include "Atomic.h"
+#include "DalvikVersion.h"
#include <stdlib.h>
#include <string.h>
@@ -110,10 +112,14 @@
/*
* Common code for *_InvokeMethod requests.
+ *
+ * If "isConstructor" is set, this returns "objectId" rather than the
+ * expected-to-be-void return value of the called function.
*/
static JdwpError finishInvoke(JdwpState* state,
const u1* buf, int dataLen, ExpandBuf* pReply,
- ObjectId threadId, ObjectId objectId, RefTypeId classId, MethodId methodId)
+ ObjectId threadId, ObjectId objectId, RefTypeId classId, MethodId methodId,
+ bool isConstructor)
{
JdwpError err = ERR_NONE;
u8* argArray = NULL;
@@ -121,6 +127,8 @@
u4 options; /* enum InvokeOptions bit flags */
int i;
+ assert(!isConstructor || objectId != 0);
+
numArgs = read4BE(&buf);
LOGV(" --> threadId=%llx objectId=%llx\n", threadId, objectId);
@@ -163,11 +171,16 @@
goto bail;
if (err == ERR_NONE) {
- int width = dvmDbgGetTagWidth(resultTag);
+ if (isConstructor) {
+ expandBufAdd1(pReply, JT_OBJECT);
+ expandBufAddObjectId(pReply, objectId);
+ } else {
+ int width = dvmDbgGetTagWidth(resultTag);
- expandBufAdd1(pReply, resultTag);
- if (width != 0)
- jdwpWriteValue(pReply, width, resultValue);
+ expandBufAdd1(pReply, resultTag);
+ if (width != 0)
+ jdwpWriteValue(pReply, width, resultValue);
+ }
expandBufAdd1(pReply, JT_OBJECT);
expandBufAddObjectId(pReply, exceptObjId);
@@ -198,8 +211,12 @@
static JdwpError handleVM_Version(JdwpState* state, const u1* buf,
int dataLen, ExpandBuf* pReply)
{
+ char tmpBuf[128];
+
/* text information on VM version */
- expandBufAddUtf8String(pReply, (const u1*) "Android DalvikVM 1.0.1");
+ sprintf(tmpBuf, "Android DalvikVM %d.%d.%d",
+ DALVIK_MAJOR_VERSION, DALVIK_MINOR_VERSION, DALVIK_BUG_VERSION);
+ expandBufAddUtf8String(pReply, (const u1*) tmpBuf);
/* JDWP version numbers */
expandBufAdd4BE(pReply, 1); // major
expandBufAdd4BE(pReply, 5); // minor
@@ -400,8 +417,10 @@
LOGV(" Req to create string '%s'\n", str);
stringId = dvmDbgCreateString(str);
- expandBufAddObjectId(pReply, stringId);
+ if (stringId == 0)
+ return ERR_OUT_OF_MEMORY;
+ expandBufAddObjectId(pReply, stringId);
return ERR_NONE;
}
@@ -652,8 +671,6 @@
const u1* buf, int dataLen, ExpandBuf* pReply)
{
RefTypeId refTypeId;
- u4 numInterfaces;
- int i;
refTypeId = dvmReadRefTypeId(&buf);
@@ -666,6 +683,25 @@
}
/*
+ * Return the class object corresponding to this type.
+ */
+static JdwpError handleRT_ClassObject(JdwpState* state,
+ const u1* buf, int dataLen, ExpandBuf* pReply)
+{
+ RefTypeId refTypeId;
+ ObjectId classObjId;
+
+ refTypeId = dvmReadRefTypeId(&buf);
+ classObjId = dvmDbgGetClassObject(refTypeId);
+
+ LOGV(" RefTypeId %llx -> ObjectId %llx\n", refTypeId, classObjId);
+
+ expandBufAddObjectId(pReply, classObjId);
+
+ return ERR_NONE;
+}
+
+/*
* Returns the value of the SourceDebugExtension attribute.
*
* JDB seems interested, but DEX files don't currently support this.
@@ -834,7 +870,36 @@
methodId = dvmReadMethodId(&buf);
return finishInvoke(state, buf, dataLen, pReply,
- threadId, 0, classId, methodId);
+ threadId, 0, classId, methodId, false);
+}
+
+/*
+ * Create a new object of the requested type, and invoke the specified
+ * constructor.
+ *
+ * Example: in IntelliJ, create a watch on "new String(myByteArray)" to
+ * see the contents of a byte[] as a string.
+ */
+static JdwpError handleCT_NewInstance(JdwpState* state,
+ const u1* buf, int dataLen, ExpandBuf* pReply)
+{
+ RefTypeId classId;
+ ObjectId threadId;
+ MethodId methodId;
+ ObjectId objectId;
+ u4 numArgs;
+
+ classId = dvmReadRefTypeId(&buf);
+ threadId = dvmReadObjectId(&buf);
+ methodId = dvmReadMethodId(&buf);
+
+ LOGV("Creating instance of %s\n", dvmDbgGetClassDescriptor(classId));
+ objectId = dvmDbgCreateObject(classId);
+ if (objectId == 0)
+ return ERR_OUT_OF_MEMORY;
+
+ return finishInvoke(state, buf, dataLen, pReply,
+ threadId, objectId, classId, methodId, true);
}
/*
@@ -1011,7 +1076,7 @@
methodId = dvmReadMethodId(&buf);
return finishInvoke(state, buf, dataLen, pReply,
- threadId, objectId, classId, methodId);
+ threadId, objectId, classId, methodId, false);
}
/*
@@ -1938,7 +2003,7 @@
//2, 8, NestedTypes
{ 2, 9, handleRT_Status, "ReferenceType.Status" },
{ 2, 10, handleRT_Interfaces, "ReferenceType.Interfaces" },
- //2, 11, ClassObject
+ { 2, 11, handleRT_ClassObject, "ReferenceType.ClassObject" },
{ 2, 12, handleRT_SourceDebugExtension,
"ReferenceType.SourceDebugExtension" },
{ 2, 13, handleRT_SignatureWithGeneric,
@@ -1955,7 +2020,7 @@
{ 3, 1, handleCT_Superclass, "ClassType.Superclass" },
{ 3, 2, handleCT_SetValues, "ClassType.SetValues" },
{ 3, 3, handleCT_InvokeMethod, "ClassType.InvokeMethod" },
- //3, 4, NewInstance
+ { 3, 4, handleCT_NewInstance, "ClassType.NewInstance" },
/* ArrayType command set (4) */
//4, 1, NewInstance
diff --git a/vm/mterp/armv5te/footer.S b/vm/mterp/armv5te/footer.S
index 90e3750..461cc66 100644
--- a/vm/mterp/armv5te/footer.S
+++ b/vm/mterp/armv5te/footer.S
@@ -11,6 +11,41 @@
.align 2
#if defined(WITH_JIT)
+#if defined(WITH_SELF_VERIFICATION)
+ .global dvmJitToInterpPunt
+dvmJitToInterpPunt:
+ mov r2,#kSVSPunt @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToInterpSingleStep
+dvmJitToInterpSingleStep:
+ mov r2,#kSVSSingleStep @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToTraceSelect
+dvmJitToTraceSelect:
+ ldr r0,[r14, #-1] @ pass our target PC
+ mov r2,#kSVSTraceSelect @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToBackwardBranch
+dvmJitToBackwardBranch:
+ ldr r0,[r14, #-1] @ pass our target PC
+ mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToInterpNormal
+dvmJitToInterpNormal:
+ ldr r0,[r14, #-1] @ pass our target PC
+ mov r2,#kSVSNormal @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToInterpNoChain
+dvmJitToInterpNoChain:
+ mov r0,rPC @ pass our target PC
+ mov r2,#kSVSNoChain @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+#else
/*
* Return from the translation cache to the interpreter when the compiler is
* having issues translating/executing a Dalvik instruction. We have to skip
@@ -127,6 +162,7 @@
bl dvmJitGetCodeAddr @ Is there a translation?
cmp r0,#0
bxne r0 @ continue native execution if so
+#endif
/*
* No translation, restore interpreter regs and start interpreting.
@@ -174,13 +210,65 @@
bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC)
cmp r0,#0
beq common_selectTrace
+#if !defined(WITH_SELF_VERIFICATION)
bxne r0 @ jump to the translation
+#else
+ bne dvmJitSelfVerificationStart @ set up self verification
+#endif
common_selectTrace:
mov r2,#kJitTSelectRequest @ ask for trace selection
str r2,[rGLUE,#offGlue_jitState]
+ mov r2,#kInterpEntryInstr @ normal entry reason
+ str r2,[rGLUE,#offGlue_entryPoint]
mov r1,#1 @ set changeInterp
b common_gotoBail
+#if defined(WITH_SELF_VERIFICATION)
+/*
+ * Save PC and registers to shadow memory for self verification mode
+ * before jumping to native translation.
+ */
+dvmJitSelfVerificationStart:
+ sub sp,sp,#4 @ allocate stack space
+ str r0,[sp,#0] @ save out dvmJitGetCodeAddr(rPC)
+ mov r0,rPC @ r0<- program counter
+ mov r1,rFP @ r1<- frame pointer
+ mov r2,rGLUE @ r2<- InterpState pointer
+ bl dvmSelfVerificationSaveState @ save registers to shadow space
+ ldr rFP,[r0,#20] @ rFP<- fp in shadow space
+ add rGLUE,r0,#24 @ rGLUE<- pointer in shadow space
+ ldr r0,[sp,#0] @ r0<- dvmJitGetCodeAddr(rPC)
+ add sp,sp,#4 @ restore stack
+ bx r0 @ jump to the translation
+
+/*
+ * Restore PC, registers, and interpState to original values
+ * before jumping back to the interpreter.
+ */
+dvmJitSelfVerificationEnd:
+ mov r1,rFP @ pass ending fp
+ bl dvmSelfVerificationRestoreState @ restore pc and fp values
+ ldr rPC,[r0,#0] @ restore PC
+ ldr rFP,[r0,#4] @ restore FP
+ ldr rGLUE,[r0,#8] @ restore InterpState
+ ldr r1,[r0,#12] @ get exitPoint
+ cmp r1,#0 @ check for punt condition
+ beq 1f
+ mov r2,#kJitSelfVerification @ ask for self verification
+ str r2,[rGLUE,#offGlue_jitState]
+ mov r2,#kInterpEntryInstr @ normal entry reason
+ str r2,[rGLUE,#offGlue_entryPoint]
+ mov r1,#1 @ set changeInterp
+ b common_gotoBail
+
+1: @ exit to interpreter without check
+ EXPORT_PC()
+ adrl rIBASE, dvmAsmInstructionStart
+ FETCH_INST()
+ GET_INST_OPCODE(ip)
+ GOTO_OPCODE(ip)
+#endif
+
#endif
/*
@@ -222,6 +310,9 @@
common_periodicChecks:
ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
+ @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
+ str r0, [rGLUE, #offGlue_entryPoint]
+
#if defined(WITH_DEBUGGER)
ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive
#endif
@@ -262,7 +353,6 @@
3: @ debugger/profiler enabled, bail out
add rPC, rPC, r9 @ update rPC
- str r0, [rGLUE, #offGlue_entryPoint]
mov r1, #1 @ "want switch" = true
b common_gotoBail
@@ -467,7 +557,8 @@
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
-.LstackOverflow:
+.LstackOverflow: @ r0=methodToCall
+ mov r1, r0 @ r1<- methodToCall
ldr r0, [rGLUE, #offGlue_self] @ r0<- self
bl dvmHandleStackOverflow
b common_exceptionThrown
diff --git a/vm/mterp/c/gotoTargets.c b/vm/mterp/c/gotoTargets.c
index 5b93583..67b3299 100644
--- a/vm/mterp/c/gotoTargets.c
+++ b/vm/mterp/c/gotoTargets.c
@@ -576,6 +576,12 @@
*/
PERIODIC_CHECKS(kInterpEntryThrow, 0);
+#if defined(WITH_JIT)
+ // Something threw during trace selection - abort the current trace
+ if (interpState->jitState == kJitTSelect) {
+ interpState->jitState = kJitTSelectEnd;
+ }
+#endif
/*
* We save off the exception and clear the exception status. While
* processing the exception we might need to load some Throwable
@@ -807,10 +813,11 @@
bottom = (u1*) newSaveArea - methodToCall->outsSize * sizeof(u4);
if (bottom < self->interpStackEnd) {
/* stack overflow */
- LOGV("Stack overflow on method call (start=%p end=%p newBot=%p size=%d '%s')\n",
+ LOGV("Stack overflow on method call (start=%p end=%p newBot=%p(%d) size=%d '%s')\n",
self->interpStackStart, self->interpStackEnd, bottom,
- self->interpStackSize, methodToCall->name);
- dvmHandleStackOverflow(self);
+ (u1*) fp - bottom, self->interpStackSize,
+ methodToCall->name);
+ dvmHandleStackOverflow(self, methodToCall);
assert(dvmCheckException(self));
GOTO_exceptionThrown();
}
diff --git a/vm/mterp/common/asm-constants.h b/vm/mterp/common/asm-constants.h
index a69247e..e157c37 100644
--- a/vm/mterp/common/asm-constants.h
+++ b/vm/mterp/common/asm-constants.h
@@ -246,6 +246,19 @@
MTERP_CONSTANT(kJitTSelectEnd, 5)
MTERP_CONSTANT(kJitSingleStep, 6)
MTERP_CONSTANT(kJitSingleStepEnd, 7)
+MTERP_CONSTANT(kJitSelfVerification, 8)
+
+#if defined(WITH_SELF_VERIFICATION)
+MTERP_CONSTANT(kSVSIdle, 0)
+MTERP_CONSTANT(kSVSStart, 1)
+MTERP_CONSTANT(kSVSPunt, 2)
+MTERP_CONSTANT(kSVSSingleStep, 3)
+MTERP_CONSTANT(kSVSTraceSelect, 4)
+MTERP_CONSTANT(kSVSNormal, 5)
+MTERP_CONSTANT(kSVSNoChain, 6)
+MTERP_CONSTANT(kSVSBackwardBranch, 7)
+MTERP_CONSTANT(kSVSDebugInterp, 8)
+#endif
#endif
/* ClassStatus enumeration */
diff --git a/vm/mterp/out/InterpAsm-armv4t.S b/vm/mterp/out/InterpAsm-armv4t.S
index 2df532f..07075bb 100644
--- a/vm/mterp/out/InterpAsm-armv4t.S
+++ b/vm/mterp/out/InterpAsm-armv4t.S
@@ -9483,6 +9483,41 @@
.align 2
#if defined(WITH_JIT)
+#if defined(WITH_SELF_VERIFICATION)
+ .global dvmJitToInterpPunt
+dvmJitToInterpPunt:
+ mov r2,#kSVSPunt @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToInterpSingleStep
+dvmJitToInterpSingleStep:
+ mov r2,#kSVSSingleStep @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToTraceSelect
+dvmJitToTraceSelect:
+ ldr r0,[r14, #-1] @ pass our target PC
+ mov r2,#kSVSTraceSelect @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToBackwardBranch
+dvmJitToBackwardBranch:
+ ldr r0,[r14, #-1] @ pass our target PC
+ mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToInterpNormal
+dvmJitToInterpNormal:
+ ldr r0,[r14, #-1] @ pass our target PC
+ mov r2,#kSVSNormal @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToInterpNoChain
+dvmJitToInterpNoChain:
+ mov r0,rPC @ pass our target PC
+ mov r2,#kSVSNoChain @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+#else
/*
* Return from the translation cache to the interpreter when the compiler is
* having issues translating/executing a Dalvik instruction. We have to skip
@@ -9599,6 +9634,7 @@
bl dvmJitGetCodeAddr @ Is there a translation?
cmp r0,#0
bxne r0 @ continue native execution if so
+#endif
/*
* No translation, restore interpreter regs and start interpreting.
@@ -9646,13 +9682,65 @@
bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC)
cmp r0,#0
beq common_selectTrace
+#if !defined(WITH_SELF_VERIFICATION)
bxne r0 @ jump to the translation
+#else
+ bne dvmJitSelfVerificationStart @ set up self verification
+#endif
common_selectTrace:
mov r2,#kJitTSelectRequest @ ask for trace selection
str r2,[rGLUE,#offGlue_jitState]
+ mov r2,#kInterpEntryInstr @ normal entry reason
+ str r2,[rGLUE,#offGlue_entryPoint]
mov r1,#1 @ set changeInterp
b common_gotoBail
+#if defined(WITH_SELF_VERIFICATION)
+/*
+ * Save PC and registers to shadow memory for self verification mode
+ * before jumping to native translation.
+ */
+dvmJitSelfVerificationStart:
+ sub sp,sp,#4 @ allocate stack space
+ str r0,[sp,#0] @ save out dvmJitGetCodeAddr(rPC)
+ mov r0,rPC @ r0<- program counter
+ mov r1,rFP @ r1<- frame pointer
+ mov r2,rGLUE @ r2<- InterpState pointer
+ bl dvmSelfVerificationSaveState @ save registers to shadow space
+ ldr rFP,[r0,#20] @ rFP<- fp in shadow space
+ add rGLUE,r0,#24 @ rGLUE<- pointer in shadow space
+ ldr r0,[sp,#0] @ r0<- dvmJitGetCodeAddr(rPC)
+ add sp,sp,#4 @ restore stack
+ bx r0 @ jump to the translation
+
+/*
+ * Restore PC, registers, and interpState to original values
+ * before jumping back to the interpreter.
+ */
+dvmJitSelfVerificationEnd:
+ mov r1,rFP @ pass ending fp
+ bl dvmSelfVerificationRestoreState @ restore pc and fp values
+ ldr rPC,[r0,#0] @ restore PC
+ ldr rFP,[r0,#4] @ restore FP
+ ldr rGLUE,[r0,#8] @ restore InterpState
+ ldr r1,[r0,#12] @ get exitPoint
+ cmp r1,#0 @ check for punt condition
+ beq 1f
+ mov r2,#kJitSelfVerification @ ask for self verification
+ str r2,[rGLUE,#offGlue_jitState]
+ mov r2,#kInterpEntryInstr @ normal entry reason
+ str r2,[rGLUE,#offGlue_entryPoint]
+ mov r1,#1 @ set changeInterp
+ b common_gotoBail
+
+1: @ exit to interpreter without check
+ EXPORT_PC()
+ adrl rIBASE, dvmAsmInstructionStart
+ FETCH_INST()
+ GET_INST_OPCODE(ip)
+ GOTO_OPCODE(ip)
+#endif
+
#endif
/*
@@ -9694,6 +9782,9 @@
common_periodicChecks:
ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
+ @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
+ str r0, [rGLUE, #offGlue_entryPoint]
+
#if defined(WITH_DEBUGGER)
ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive
#endif
@@ -9734,7 +9825,6 @@
3: @ debugger/profiler enabled, bail out
add rPC, rPC, r9 @ update rPC
- str r0, [rGLUE, #offGlue_entryPoint]
mov r1, #1 @ "want switch" = true
b common_gotoBail
@@ -9939,7 +10029,8 @@
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
-.LstackOverflow:
+.LstackOverflow: @ r0=methodToCall
+ mov r1, r0 @ r1<- methodToCall
ldr r0, [rGLUE, #offGlue_self] @ r0<- self
bl dvmHandleStackOverflow
b common_exceptionThrown
diff --git a/vm/mterp/out/InterpAsm-armv5te-vfp.S b/vm/mterp/out/InterpAsm-armv5te-vfp.S
index 61b2697..55ac716 100644
--- a/vm/mterp/out/InterpAsm-armv5te-vfp.S
+++ b/vm/mterp/out/InterpAsm-armv5te-vfp.S
@@ -9001,6 +9001,41 @@
.align 2
#if defined(WITH_JIT)
+#if defined(WITH_SELF_VERIFICATION)
+ .global dvmJitToInterpPunt
+dvmJitToInterpPunt:
+ mov r2,#kSVSPunt @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToInterpSingleStep
+dvmJitToInterpSingleStep:
+ mov r2,#kSVSSingleStep @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToTraceSelect
+dvmJitToTraceSelect:
+ ldr r0,[r14, #-1] @ pass our target PC
+ mov r2,#kSVSTraceSelect @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToBackwardBranch
+dvmJitToBackwardBranch:
+ ldr r0,[r14, #-1] @ pass our target PC
+ mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToInterpNormal
+dvmJitToInterpNormal:
+ ldr r0,[r14, #-1] @ pass our target PC
+ mov r2,#kSVSNormal @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToInterpNoChain
+dvmJitToInterpNoChain:
+ mov r0,rPC @ pass our target PC
+ mov r2,#kSVSNoChain @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+#else
/*
* Return from the translation cache to the interpreter when the compiler is
* having issues translating/executing a Dalvik instruction. We have to skip
@@ -9117,6 +9152,7 @@
bl dvmJitGetCodeAddr @ Is there a translation?
cmp r0,#0
bxne r0 @ continue native execution if so
+#endif
/*
* No translation, restore interpreter regs and start interpreting.
@@ -9164,13 +9200,65 @@
bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC)
cmp r0,#0
beq common_selectTrace
+#if !defined(WITH_SELF_VERIFICATION)
bxne r0 @ jump to the translation
+#else
+ bne dvmJitSelfVerificationStart @ set up self verification
+#endif
common_selectTrace:
mov r2,#kJitTSelectRequest @ ask for trace selection
str r2,[rGLUE,#offGlue_jitState]
+ mov r2,#kInterpEntryInstr @ normal entry reason
+ str r2,[rGLUE,#offGlue_entryPoint]
mov r1,#1 @ set changeInterp
b common_gotoBail
+#if defined(WITH_SELF_VERIFICATION)
+/*
+ * Save PC and registers to shadow memory for self verification mode
+ * before jumping to native translation.
+ */
+dvmJitSelfVerificationStart:
+ sub sp,sp,#4 @ allocate stack space
+ str r0,[sp,#0] @ save out dvmJitGetCodeAddr(rPC)
+ mov r0,rPC @ r0<- program counter
+ mov r1,rFP @ r1<- frame pointer
+ mov r2,rGLUE @ r2<- InterpState pointer
+ bl dvmSelfVerificationSaveState @ save registers to shadow space
+ ldr rFP,[r0,#20] @ rFP<- fp in shadow space
+ add rGLUE,r0,#24 @ rGLUE<- pointer in shadow space
+ ldr r0,[sp,#0] @ r0<- dvmJitGetCodeAddr(rPC)
+ add sp,sp,#4 @ restore stack
+ bx r0 @ jump to the translation
+
+/*
+ * Restore PC, registers, and interpState to original values
+ * before jumping back to the interpreter.
+ */
+dvmJitSelfVerificationEnd:
+ mov r1,rFP @ pass ending fp
+ bl dvmSelfVerificationRestoreState @ restore pc and fp values
+ ldr rPC,[r0,#0] @ restore PC
+ ldr rFP,[r0,#4] @ restore FP
+ ldr rGLUE,[r0,#8] @ restore InterpState
+ ldr r1,[r0,#12] @ get exitPoint
+ cmp r1,#0 @ check for punt condition
+ beq 1f
+ mov r2,#kJitSelfVerification @ ask for self verification
+ str r2,[rGLUE,#offGlue_jitState]
+ mov r2,#kInterpEntryInstr @ normal entry reason
+ str r2,[rGLUE,#offGlue_entryPoint]
+ mov r1,#1 @ set changeInterp
+ b common_gotoBail
+
+1: @ exit to interpreter without check
+ EXPORT_PC()
+ adrl rIBASE, dvmAsmInstructionStart
+ FETCH_INST()
+ GET_INST_OPCODE(ip)
+ GOTO_OPCODE(ip)
+#endif
+
#endif
/*
@@ -9212,6 +9300,9 @@
common_periodicChecks:
ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
+ @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
+ str r0, [rGLUE, #offGlue_entryPoint]
+
#if defined(WITH_DEBUGGER)
ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive
#endif
@@ -9252,7 +9343,6 @@
3: @ debugger/profiler enabled, bail out
add rPC, rPC, r9 @ update rPC
- str r0, [rGLUE, #offGlue_entryPoint]
mov r1, #1 @ "want switch" = true
b common_gotoBail
@@ -9457,7 +9547,8 @@
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
-.LstackOverflow:
+.LstackOverflow: @ r0=methodToCall
+ mov r1, r0 @ r1<- methodToCall
ldr r0, [rGLUE, #offGlue_self] @ r0<- self
bl dvmHandleStackOverflow
b common_exceptionThrown
diff --git a/vm/mterp/out/InterpAsm-armv5te.S b/vm/mterp/out/InterpAsm-armv5te.S
index bafd442..55f6fee 100644
--- a/vm/mterp/out/InterpAsm-armv5te.S
+++ b/vm/mterp/out/InterpAsm-armv5te.S
@@ -9477,6 +9477,41 @@
.align 2
#if defined(WITH_JIT)
+#if defined(WITH_SELF_VERIFICATION)
+ .global dvmJitToInterpPunt
+dvmJitToInterpPunt:
+ mov r2,#kSVSPunt @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToInterpSingleStep
+dvmJitToInterpSingleStep:
+ mov r2,#kSVSSingleStep @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToTraceSelect
+dvmJitToTraceSelect:
+ ldr r0,[r14, #-1] @ pass our target PC
+ mov r2,#kSVSTraceSelect @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToBackwardBranch
+dvmJitToBackwardBranch:
+ ldr r0,[r14, #-1] @ pass our target PC
+ mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToInterpNormal
+dvmJitToInterpNormal:
+ ldr r0,[r14, #-1] @ pass our target PC
+ mov r2,#kSVSNormal @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToInterpNoChain
+dvmJitToInterpNoChain:
+ mov r0,rPC @ pass our target PC
+ mov r2,#kSVSNoChain @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+#else
/*
* Return from the translation cache to the interpreter when the compiler is
* having issues translating/executing a Dalvik instruction. We have to skip
@@ -9593,6 +9628,7 @@
bl dvmJitGetCodeAddr @ Is there a translation?
cmp r0,#0
bxne r0 @ continue native execution if so
+#endif
/*
* No translation, restore interpreter regs and start interpreting.
@@ -9640,13 +9676,65 @@
bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC)
cmp r0,#0
beq common_selectTrace
+#if !defined(WITH_SELF_VERIFICATION)
bxne r0 @ jump to the translation
+#else
+ bne dvmJitSelfVerificationStart @ set up self verification
+#endif
common_selectTrace:
mov r2,#kJitTSelectRequest @ ask for trace selection
str r2,[rGLUE,#offGlue_jitState]
+ mov r2,#kInterpEntryInstr @ normal entry reason
+ str r2,[rGLUE,#offGlue_entryPoint]
mov r1,#1 @ set changeInterp
b common_gotoBail
+#if defined(WITH_SELF_VERIFICATION)
+/*
+ * Save PC and registers to shadow memory for self verification mode
+ * before jumping to native translation.
+ */
+dvmJitSelfVerificationStart:
+ sub sp,sp,#4 @ allocate stack space
+ str r0,[sp,#0] @ save out dvmJitGetCodeAddr(rPC)
+ mov r0,rPC @ r0<- program counter
+ mov r1,rFP @ r1<- frame pointer
+ mov r2,rGLUE @ r2<- InterpState pointer
+ bl dvmSelfVerificationSaveState @ save registers to shadow space
+ ldr rFP,[r0,#20] @ rFP<- fp in shadow space
+ add rGLUE,r0,#24 @ rGLUE<- pointer in shadow space
+ ldr r0,[sp,#0] @ r0<- dvmJitGetCodeAddr(rPC)
+ add sp,sp,#4 @ restore stack
+ bx r0 @ jump to the translation
+
+/*
+ * Restore PC, registers, and interpState to original values
+ * before jumping back to the interpreter.
+ */
+dvmJitSelfVerificationEnd:
+ mov r1,rFP @ pass ending fp
+ bl dvmSelfVerificationRestoreState @ restore pc and fp values
+ ldr rPC,[r0,#0] @ restore PC
+ ldr rFP,[r0,#4] @ restore FP
+ ldr rGLUE,[r0,#8] @ restore InterpState
+ ldr r1,[r0,#12] @ get exitPoint
+ cmp r1,#0 @ check for punt condition
+ beq 1f
+ mov r2,#kJitSelfVerification @ ask for self verification
+ str r2,[rGLUE,#offGlue_jitState]
+ mov r2,#kInterpEntryInstr @ normal entry reason
+ str r2,[rGLUE,#offGlue_entryPoint]
+ mov r1,#1 @ set changeInterp
+ b common_gotoBail
+
+1: @ exit to interpreter without check
+ EXPORT_PC()
+ adrl rIBASE, dvmAsmInstructionStart
+ FETCH_INST()
+ GET_INST_OPCODE(ip)
+ GOTO_OPCODE(ip)
+#endif
+
#endif
/*
@@ -9688,6 +9776,9 @@
common_periodicChecks:
ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
+ @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
+ str r0, [rGLUE, #offGlue_entryPoint]
+
#if defined(WITH_DEBUGGER)
ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive
#endif
@@ -9728,7 +9819,6 @@
3: @ debugger/profiler enabled, bail out
add rPC, rPC, r9 @ update rPC
- str r0, [rGLUE, #offGlue_entryPoint]
mov r1, #1 @ "want switch" = true
b common_gotoBail
@@ -9933,7 +10023,8 @@
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
-.LstackOverflow:
+.LstackOverflow: @ r0=methodToCall
+ mov r1, r0 @ r1<- methodToCall
ldr r0, [rGLUE, #offGlue_self] @ r0<- self
bl dvmHandleStackOverflow
b common_exceptionThrown
diff --git a/vm/mterp/out/InterpAsm-armv7-a.S b/vm/mterp/out/InterpAsm-armv7-a.S
index 8d018c1..3c896ae 100644
--- a/vm/mterp/out/InterpAsm-armv7-a.S
+++ b/vm/mterp/out/InterpAsm-armv7-a.S
@@ -8937,6 +8937,41 @@
.align 2
#if defined(WITH_JIT)
+#if defined(WITH_SELF_VERIFICATION)
+ .global dvmJitToInterpPunt
+dvmJitToInterpPunt:
+ mov r2,#kSVSPunt @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToInterpSingleStep
+dvmJitToInterpSingleStep:
+ mov r2,#kSVSSingleStep @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToTraceSelect
+dvmJitToTraceSelect:
+ ldr r0,[r14, #-1] @ pass our target PC
+ mov r2,#kSVSTraceSelect @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToBackwardBranch
+dvmJitToBackwardBranch:
+ ldr r0,[r14, #-1] @ pass our target PC
+ mov r2,#kSVSBackwardBranch @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToInterpNormal
+dvmJitToInterpNormal:
+ ldr r0,[r14, #-1] @ pass our target PC
+ mov r2,#kSVSNormal @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+
+ .global dvmJitToInterpNoChain
+dvmJitToInterpNoChain:
+ mov r0,rPC @ pass our target PC
+ mov r2,#kSVSNoChain @ r2<- interpreter entry point
+ b dvmJitSelfVerificationEnd @ doesn't return
+#else
/*
* Return from the translation cache to the interpreter when the compiler is
* having issues translating/executing a Dalvik instruction. We have to skip
@@ -9053,6 +9088,7 @@
bl dvmJitGetCodeAddr @ Is there a translation?
cmp r0,#0
bxne r0 @ continue native execution if so
+#endif
/*
* No translation, restore interpreter regs and start interpreting.
@@ -9100,13 +9136,65 @@
bl dvmJitGetCodeAddr @ r0<- dvmJitGetCodeAddr(rPC)
cmp r0,#0
beq common_selectTrace
+#if !defined(WITH_SELF_VERIFICATION)
bxne r0 @ jump to the translation
+#else
+ bne dvmJitSelfVerificationStart @ set up self verification
+#endif
common_selectTrace:
mov r2,#kJitTSelectRequest @ ask for trace selection
str r2,[rGLUE,#offGlue_jitState]
+ mov r2,#kInterpEntryInstr @ normal entry reason
+ str r2,[rGLUE,#offGlue_entryPoint]
mov r1,#1 @ set changeInterp
b common_gotoBail
+#if defined(WITH_SELF_VERIFICATION)
+/*
+ * Save PC and registers to shadow memory for self verification mode
+ * before jumping to native translation.
+ */
+dvmJitSelfVerificationStart:
+ sub sp,sp,#4 @ allocate stack space
+ str r0,[sp,#0] @ save out dvmJitGetCodeAddr(rPC)
+ mov r0,rPC @ r0<- program counter
+ mov r1,rFP @ r1<- frame pointer
+ mov r2,rGLUE @ r2<- InterpState pointer
+ bl dvmSelfVerificationSaveState @ save registers to shadow space
+ ldr rFP,[r0,#20] @ rFP<- fp in shadow space
+ add rGLUE,r0,#24 @ rGLUE<- pointer in shadow space
+ ldr r0,[sp,#0] @ r0<- dvmJitGetCodeAddr(rPC)
+ add sp,sp,#4 @ restore stack
+ bx r0 @ jump to the translation
+
+/*
+ * Restore PC, registers, and interpState to original values
+ * before jumping back to the interpreter.
+ */
+dvmJitSelfVerificationEnd:
+ mov r1,rFP @ pass ending fp
+ bl dvmSelfVerificationRestoreState @ restore pc and fp values
+ ldr rPC,[r0,#0] @ restore PC
+ ldr rFP,[r0,#4] @ restore FP
+ ldr rGLUE,[r0,#8] @ restore InterpState
+ ldr r1,[r0,#12] @ get exitPoint
+ cmp r1,#0 @ check for punt condition
+ beq 1f
+ mov r2,#kJitSelfVerification @ ask for self verification
+ str r2,[rGLUE,#offGlue_jitState]
+ mov r2,#kInterpEntryInstr @ normal entry reason
+ str r2,[rGLUE,#offGlue_entryPoint]
+ mov r1,#1 @ set changeInterp
+ b common_gotoBail
+
+1: @ exit to interpreter without check
+ EXPORT_PC()
+ adrl rIBASE, dvmAsmInstructionStart
+ FETCH_INST()
+ GET_INST_OPCODE(ip)
+ GOTO_OPCODE(ip)
+#endif
+
#endif
/*
@@ -9148,6 +9236,9 @@
common_periodicChecks:
ldr r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
+ @ speculatively store r0 before it is clobbered by dvmCheckSuspendPending
+ str r0, [rGLUE, #offGlue_entryPoint]
+
#if defined(WITH_DEBUGGER)
ldr r1, [rGLUE, #offGlue_pDebuggerActive] @ r1<- &debuggerActive
#endif
@@ -9188,7 +9279,6 @@
3: @ debugger/profiler enabled, bail out
add rPC, rPC, r9 @ update rPC
- str r0, [rGLUE, #offGlue_entryPoint]
mov r1, #1 @ "want switch" = true
b common_gotoBail
@@ -9393,7 +9483,8 @@
GET_INST_OPCODE(ip) @ extract opcode from rINST
GOTO_OPCODE(ip) @ jump to next instruction
-.LstackOverflow:
+.LstackOverflow: @ r0=methodToCall
+ mov r1, r0 @ r1<- methodToCall
ldr r0, [rGLUE, #offGlue_self] @ r0<- self
bl dvmHandleStackOverflow
b common_exceptionThrown
diff --git a/vm/mterp/out/InterpAsm-x86.S b/vm/mterp/out/InterpAsm-x86.S
index 79c98f6..c25071e 100644
--- a/vm/mterp/out/InterpAsm-x86.S
+++ b/vm/mterp/out/InterpAsm-x86.S
@@ -8727,11 +8727,12 @@
ADVANCE_PC(3)
GOTO_NEXT # jump to next instruction
-.LstackOverflow:
+.LstackOverflow: # eax=methodToCall
+ movl %eax, OUT_ARG1(%esp) # push parameter methodToCall
GET_GLUE(%eax) # %eax<- pMterpGlue
movl offGlue_self(%eax), %eax # %eax<- glue->self
movl %eax, OUT_ARG0(%esp) # push parameter self
- call dvmHandleStackOverflow # call: (Thread* self)
+ call dvmHandleStackOverflow # call: (Thread* self, Method* meth)
UNSPILL(rPC) # return: void
jmp common_exceptionThrown # handle exception
diff --git a/vm/mterp/out/InterpC-allstubs.c b/vm/mterp/out/InterpC-allstubs.c
index 4e832d8..1d31227 100644
--- a/vm/mterp/out/InterpC-allstubs.c
+++ b/vm/mterp/out/InterpC-allstubs.c
@@ -3609,6 +3609,12 @@
*/
PERIODIC_CHECKS(kInterpEntryThrow, 0);
+#if defined(WITH_JIT)
+ // Something threw during trace selection - abort the current trace
+ if (interpState->jitState == kJitTSelect) {
+ interpState->jitState = kJitTSelectEnd;
+ }
+#endif
/*
* We save off the exception and clear the exception status. While
* processing the exception we might need to load some Throwable
@@ -3840,10 +3846,11 @@
bottom = (u1*) newSaveArea - methodToCall->outsSize * sizeof(u4);
if (bottom < self->interpStackEnd) {
/* stack overflow */
- LOGV("Stack overflow on method call (start=%p end=%p newBot=%p size=%d '%s')\n",
+ LOGV("Stack overflow on method call (start=%p end=%p newBot=%p(%d) size=%d '%s')\n",
self->interpStackStart, self->interpStackEnd, bottom,
- self->interpStackSize, methodToCall->name);
- dvmHandleStackOverflow(self);
+ (u1*) fp - bottom, self->interpStackSize,
+ methodToCall->name);
+ dvmHandleStackOverflow(self, methodToCall);
assert(dvmCheckException(self));
GOTO_exceptionThrown();
}
diff --git a/vm/mterp/out/InterpC-portdbg.c b/vm/mterp/out/InterpC-portdbg.c
index 4b92639..03fe00e 100644
--- a/vm/mterp/out/InterpC-portdbg.c
+++ b/vm/mterp/out/InterpC-portdbg.c
@@ -421,11 +421,9 @@
checkDebugAndProf(pc, fp, self, curMethod, &debugIsMethodEntry)
#if defined(WITH_JIT)
-#define CHECK_JIT() \
- if (dvmCheckJit(pc, self, interpState)) GOTO_bail_switch()
+#define CHECK_JIT() (dvmCheckJit(pc, self, interpState))
#else
-#define CHECK_JIT() \
- ((void)0)
+#define CHECK_JIT() (0)
#endif
/* File: portable/stubdefs.c */
@@ -459,7 +457,7 @@
inst = FETCH(0); \
CHECK_DEBUG_AND_PROF(); \
CHECK_TRACKED_REFS(); \
- CHECK_JIT(); \
+ if (CHECK_JIT()) GOTO_bail_switch(); \
goto *handlerTable[INST_INST(inst)]; \
}
#else
@@ -520,7 +518,6 @@
} \
}
-
/* File: c/opcommon.c */
/* forward declarations of goto targets */
GOTO_TARGET_DECL(filledNewArray, bool methodCallRange);
@@ -1498,13 +1495,22 @@
/* Check to see if we've got a trace selection request. If we do,
* but something is amiss, revert to the fast interpreter.
*/
+#if !defined(WITH_SELF_VERIFICATION)
if (dvmJitCheckTraceRequest(self,interpState)) {
interpState->nextMode = INTERP_STD;
//LOGD("** something wrong, exiting\n");
return true;
}
-#endif
-#endif
+#else
+ if (interpState->jitState != kJitSelfVerification &&
+ dvmJitCheckTraceRequest(self,interpState)) {
+ interpState->nextMode = INTERP_STD;
+ //LOGD("** something wrong, exiting\n");
+ return true;
+ }
+#endif /* WITH_SELF_VERIFICATION */
+#endif /* INTERP_TYPE == INTERP_DBG */
+#endif /* WITH_JIT */
/* copy state in */
curMethod = interpState->method;
@@ -1537,6 +1543,7 @@
/* just fall through to instruction loop or threaded kickstart */
break;
case kInterpEntryReturn:
+ CHECK_JIT();
goto returnFromMethod;
case kInterpEntryThrow:
goto exceptionThrown;
@@ -3900,6 +3907,12 @@
*/
PERIODIC_CHECKS(kInterpEntryThrow, 0);
+#if defined(WITH_JIT)
+ // Something threw during trace selection - abort the current trace
+ if (interpState->jitState == kJitTSelect) {
+ interpState->jitState = kJitTSelectEnd;
+ }
+#endif
/*
* We save off the exception and clear the exception status. While
* processing the exception we might need to load some Throwable
@@ -4131,10 +4144,11 @@
bottom = (u1*) newSaveArea - methodToCall->outsSize * sizeof(u4);
if (bottom < self->interpStackEnd) {
/* stack overflow */
- LOGV("Stack overflow on method call (start=%p end=%p newBot=%p size=%d '%s')\n",
+ LOGV("Stack overflow on method call (start=%p end=%p newBot=%p(%d) size=%d '%s')\n",
self->interpStackStart, self->interpStackEnd, bottom,
- self->interpStackSize, methodToCall->name);
- dvmHandleStackOverflow(self);
+ (u1*) fp - bottom, self->interpStackSize,
+ methodToCall->name);
+ dvmHandleStackOverflow(self, methodToCall);
assert(dvmCheckException(self));
GOTO_exceptionThrown();
}
diff --git a/vm/mterp/out/InterpC-portstd.c b/vm/mterp/out/InterpC-portstd.c
index 1db6e87..a092da0 100644
--- a/vm/mterp/out/InterpC-portstd.c
+++ b/vm/mterp/out/InterpC-portstd.c
@@ -419,7 +419,7 @@
#define CHECK_DEBUG_AND_PROF() ((void)0)
-#define CHECK_JIT() ((void)0)
+#define CHECK_JIT() (0)
/* File: portable/stubdefs.c */
/*
@@ -452,7 +452,7 @@
inst = FETCH(0); \
CHECK_DEBUG_AND_PROF(); \
CHECK_TRACKED_REFS(); \
- CHECK_JIT(); \
+ if (CHECK_JIT()) GOTO_bail_switch(); \
goto *handlerTable[INST_INST(inst)]; \
}
#else
@@ -513,7 +513,6 @@
} \
}
-
/* File: c/opcommon.c */
/* forward declarations of goto targets */
GOTO_TARGET_DECL(filledNewArray, bool methodCallRange);
@@ -1212,13 +1211,22 @@
/* Check to see if we've got a trace selection request. If we do,
* but something is amiss, revert to the fast interpreter.
*/
+#if !defined(WITH_SELF_VERIFICATION)
if (dvmJitCheckTraceRequest(self,interpState)) {
interpState->nextMode = INTERP_STD;
//LOGD("** something wrong, exiting\n");
return true;
}
-#endif
-#endif
+#else
+ if (interpState->jitState != kJitSelfVerification &&
+ dvmJitCheckTraceRequest(self,interpState)) {
+ interpState->nextMode = INTERP_STD;
+ //LOGD("** something wrong, exiting\n");
+ return true;
+ }
+#endif /* WITH_SELF_VERIFICATION */
+#endif /* INTERP_TYPE == INTERP_DBG */
+#endif /* WITH_JIT */
/* copy state in */
curMethod = interpState->method;
@@ -1251,6 +1259,7 @@
/* just fall through to instruction loop or threaded kickstart */
break;
case kInterpEntryReturn:
+ CHECK_JIT();
goto returnFromMethod;
case kInterpEntryThrow:
goto exceptionThrown;
@@ -3614,6 +3623,12 @@
*/
PERIODIC_CHECKS(kInterpEntryThrow, 0);
+#if defined(WITH_JIT)
+ // Something threw during trace selection - abort the current trace
+ if (interpState->jitState == kJitTSelect) {
+ interpState->jitState = kJitTSelectEnd;
+ }
+#endif
/*
* We save off the exception and clear the exception status. While
* processing the exception we might need to load some Throwable
@@ -3845,10 +3860,11 @@
bottom = (u1*) newSaveArea - methodToCall->outsSize * sizeof(u4);
if (bottom < self->interpStackEnd) {
/* stack overflow */
- LOGV("Stack overflow on method call (start=%p end=%p newBot=%p size=%d '%s')\n",
+ LOGV("Stack overflow on method call (start=%p end=%p newBot=%p(%d) size=%d '%s')\n",
self->interpStackStart, self->interpStackEnd, bottom,
- self->interpStackSize, methodToCall->name);
- dvmHandleStackOverflow(self);
+ (u1*) fp - bottom, self->interpStackSize,
+ methodToCall->name);
+ dvmHandleStackOverflow(self, methodToCall);
assert(dvmCheckException(self));
GOTO_exceptionThrown();
}
diff --git a/vm/mterp/out/InterpC-x86.c b/vm/mterp/out/InterpC-x86.c
index 07536c4..fa2dfa8 100644
--- a/vm/mterp/out/InterpC-x86.c
+++ b/vm/mterp/out/InterpC-x86.c
@@ -1764,6 +1764,12 @@
*/
PERIODIC_CHECKS(kInterpEntryThrow, 0);
+#if defined(WITH_JIT)
+ // Something threw during trace selection - abort the current trace
+ if (interpState->jitState == kJitTSelect) {
+ interpState->jitState = kJitTSelectEnd;
+ }
+#endif
/*
* We save off the exception and clear the exception status. While
* processing the exception we might need to load some Throwable
@@ -1995,10 +2001,11 @@
bottom = (u1*) newSaveArea - methodToCall->outsSize * sizeof(u4);
if (bottom < self->interpStackEnd) {
/* stack overflow */
- LOGV("Stack overflow on method call (start=%p end=%p newBot=%p size=%d '%s')\n",
+ LOGV("Stack overflow on method call (start=%p end=%p newBot=%p(%d) size=%d '%s')\n",
self->interpStackStart, self->interpStackEnd, bottom,
- self->interpStackSize, methodToCall->name);
- dvmHandleStackOverflow(self);
+ (u1*) fp - bottom, self->interpStackSize,
+ methodToCall->name);
+ dvmHandleStackOverflow(self, methodToCall);
assert(dvmCheckException(self));
GOTO_exceptionThrown();
}
diff --git a/vm/mterp/portable/entry.c b/vm/mterp/portable/entry.c
index 9c7c2d6..4a6ed4e 100644
--- a/vm/mterp/portable/entry.c
+++ b/vm/mterp/portable/entry.c
@@ -47,13 +47,22 @@
/* Check to see if we've got a trace selection request. If we do,
* but something is amiss, revert to the fast interpreter.
*/
+#if !defined(WITH_SELF_VERIFICATION)
if (dvmJitCheckTraceRequest(self,interpState)) {
interpState->nextMode = INTERP_STD;
//LOGD("** something wrong, exiting\n");
return true;
}
-#endif
-#endif
+#else
+ if (interpState->jitState != kJitSelfVerification &&
+ dvmJitCheckTraceRequest(self,interpState)) {
+ interpState->nextMode = INTERP_STD;
+ //LOGD("** something wrong, exiting\n");
+ return true;
+ }
+#endif /* WITH_SELF_VERIFICATION */
+#endif /* INTERP_TYPE == INTERP_DBG */
+#endif /* WITH_JIT */
/* copy state in */
curMethod = interpState->method;
@@ -86,6 +95,7 @@
/* just fall through to instruction loop or threaded kickstart */
break;
case kInterpEntryReturn:
+ CHECK_JIT();
goto returnFromMethod;
case kInterpEntryThrow:
goto exceptionThrown;
diff --git a/vm/mterp/portable/portdbg.c b/vm/mterp/portable/portdbg.c
index 04132cb..014d866 100644
--- a/vm/mterp/portable/portdbg.c
+++ b/vm/mterp/portable/portdbg.c
@@ -5,9 +5,7 @@
checkDebugAndProf(pc, fp, self, curMethod, &debugIsMethodEntry)
#if defined(WITH_JIT)
-#define CHECK_JIT() \
- if (dvmCheckJit(pc, self, interpState)) GOTO_bail_switch()
+#define CHECK_JIT() (dvmCheckJit(pc, self, interpState))
#else
-#define CHECK_JIT() \
- ((void)0)
+#define CHECK_JIT() (0)
#endif
diff --git a/vm/mterp/portable/portstd.c b/vm/mterp/portable/portstd.c
index f55e8e7..f13bca7 100644
--- a/vm/mterp/portable/portstd.c
+++ b/vm/mterp/portable/portstd.c
@@ -3,4 +3,4 @@
#define CHECK_DEBUG_AND_PROF() ((void)0)
-#define CHECK_JIT() ((void)0)
+#define CHECK_JIT() (0)
diff --git a/vm/mterp/portable/stubdefs.c b/vm/mterp/portable/stubdefs.c
index 305aebb..717e746 100644
--- a/vm/mterp/portable/stubdefs.c
+++ b/vm/mterp/portable/stubdefs.c
@@ -28,7 +28,7 @@
inst = FETCH(0); \
CHECK_DEBUG_AND_PROF(); \
CHECK_TRACKED_REFS(); \
- CHECK_JIT(); \
+ if (CHECK_JIT()) GOTO_bail_switch(); \
goto *handlerTable[INST_INST(inst)]; \
}
#else
@@ -88,4 +88,3 @@
GOTO_bail_switch(); \
} \
}
-
diff --git a/vm/mterp/x86/footer.S b/vm/mterp/x86/footer.S
index c39fa16..8ed6c66 100644
--- a/vm/mterp/x86/footer.S
+++ b/vm/mterp/x86/footer.S
@@ -227,11 +227,12 @@
ADVANCE_PC(3)
GOTO_NEXT # jump to next instruction
-.LstackOverflow:
+.LstackOverflow: # eax=methodToCall
+ movl %eax, OUT_ARG1(%esp) # push parameter methodToCall
GET_GLUE(%eax) # %eax<- pMterpGlue
movl offGlue_self(%eax), %eax # %eax<- glue->self
movl %eax, OUT_ARG0(%esp) # push parameter self
- call dvmHandleStackOverflow # call: (Thread* self)
+ call dvmHandleStackOverflow # call: (Thread* self, Method* meth)
UNSPILL(rPC) # return: void
jmp common_exceptionThrown # handle exception
diff --git a/vm/native/java_lang_Runtime.c b/vm/native/java_lang_Runtime.c
index 1278f03..b5c0aee 100644
--- a/vm/native/java_lang_Runtime.c
+++ b/vm/native/java_lang_Runtime.c
@@ -53,6 +53,9 @@
LOGW("JNI exit hook returned\n");
}
LOGD("Calling exit(%d)\n", status);
+#if defined(WITH_JIT) && defined(WITH_JIT_TUNING)
+ dvmCompilerDumpStats();
+#endif
exit(status);
}
@@ -161,4 +164,3 @@
Dalvik_java_lang_Runtime_totalMemory },
{ NULL, NULL, NULL },
};
-
diff --git a/vm/native/java_lang_Throwable.c b/vm/native/java_lang_Throwable.c
index 3cd0e2e..cb94f0f 100644
--- a/vm/native/java_lang_Throwable.c
+++ b/vm/native/java_lang_Throwable.c
@@ -47,6 +47,11 @@
Object* stackState = (Object*) args[0];
ArrayObject* elements = NULL;
+ if (stackState == NULL) {
+ LOGW("getStackTrace() called but no trace available\n");
+ RETURN_PTR(NULL); /* could throw NPE; currently caller will do so */
+ }
+
elements = dvmGetStackTrace(stackState);
RETURN_PTR(elements);
}
diff --git a/vm/oo/Class.c b/vm/oo/Class.c
index 115a122..cc461e7 100644
--- a/vm/oo/Class.c
+++ b/vm/oo/Class.c
@@ -1395,7 +1395,7 @@
* making it an informative abort rather than an assert).
*/
if (dvmCheckException(self)) {
- LOGE("Class lookup %s attemped while exception %s pending\n",
+ LOGE("Class lookup %s attempted while exception %s pending\n",
descriptor, dvmGetException(self)->clazz->descriptor);
dvmDumpAllThreads(false);
dvmAbort();
@@ -2418,7 +2418,7 @@
* f->byteOffset is the offset from the beginning of
* obj, not the offset into obj->instanceData.
*/
- assert(f->byteOffset >= CLASS_SMALLEST_OFFSET);
+ assert(f->byteOffset >= (int) CLASS_SMALLEST_OFFSET);
assert((f->byteOffset & (CLASS_OFFSET_ALIGNMENT - 1)) == 0);
if (CLASS_CAN_ENCODE_OFFSET(f->byteOffset)) {
u4 newBit = CLASS_BIT_FROM_OFFSET(f->byteOffset);
diff --git a/vm/test/TestIndirectRefTable.c b/vm/test/TestIndirectRefTable.c
index 64d843c..25f1dd1 100644
--- a/vm/test/TestIndirectRefTable.c
+++ b/vm/test/TestIndirectRefTable.c
@@ -245,12 +245,15 @@
dvmRemoveFromIndirectRefTable(&irt, cookie, iref0);
iref1 = dvmAddToIndirectRefTable(&irt, cookie, obj0);
if (iref0 != iref1) {
+ /* try 0, should not work */
if (dvmRemoveFromIndirectRefTable(&irt, cookie, iref0)) {
LOGE("temporal del succeeded (%p vs %p)\n", iref0, iref1);
goto bail;
}
- } else {
- dvmRemoveFromIndirectRefTable(&irt, cookie, iref1);
+ }
+ if (!dvmRemoveFromIndirectRefTable(&irt, cookie, iref1)) {
+ LOGE("temporal cleanup failed\n");
+ goto bail;
}
if (dvmIndirectRefTableEntries(&irt) != 0) {
LOGE("temporal del not empty\n");